关于 awk:如何在 shell 中打印到文本文件时保留新行?

How to preserve new lines while printing to a text file in shell?

我必须在一个 txt 文件中打印出一些值。
它们具有以下格式

1
input="Sno;Name;Field1;Field2"

但是输出必须是:

1
2
3
4
Sno-Name
FIELDS ALLOCATED:
Field1
Field2

我是这样做的:

1
2
3
 echo $input | $(awk -F';' '{print $1"-"$2}') >>$txtfile
 echo"FIELDS ALLOCATED:">>$txtfile
 echo"$input" | cut -d';' -f 3,4 >>$txtfile

这很容易。但是,问题是 Field1 或 Field2 可以包含新行。每当发生这种情况时,cut 或 awk 都不会读取字段编号 4 并将其视为新行。帮助我如何从给定的输入格式打印两个字段(保留新行)。


如果输入格式正确,则可以收集输入行,直到有四个字段。

1
2
3
4
5
6
awk -F ';' 'r { $0 = r ORS $0 }
    NR<4 { next }
    {   print $1"-" $2
        print"FIELDS ALLOCATED:"
        print $3; print $4
        print""; r="" }' file


单个 gnu-awk 可以用 FPAT 和空 RS 完成工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
input=$'Sno;Name;Field1\
Foo;Field2'

awk -v RS= -v FPAT='[^;]+' '{
    printf"%s-%s\
FIELDS ALLOCATED:\
%s\
%s\
", $1, $2, $3, $4}' <<<"$input"

Sno-Name
FIELDS ALLOCATED:
Field1
Foo
Field2


只需更改awk - RS中的输入记录分隔符。为了清楚起见,在每个字段周围添加了 < 和 >。

编辑:通过在 here-doc 数据的末尾添加 \\';\\' 以及另一个条件来删除额外的尾随换行符。

1
2
3
4
5
6
7
8
9
input="Sno;Name;Fie
ld1;Fi
eld2"

awk 'BEGIN{RS=";"} NR==1{f1=$0};
     NR==2{print f1"-" $0; print"FIELDS ALLOCATED:"}
     $0=="\
"{next}
     NR>2{print"<" $0">"}' <<<"$input;"

给予:

1
2
3
4
5
6
Sno-Name
FIELDS ALLOCATED:
<Fie
ld1>
<Fi
eld2>


1
2
3
4
5
6
input=$'Sno;Name;Field1\
Foo;Field2'

awk 'BEGIN{ RS ="\
\
+" ; FS =";" } { print $1"-"$2; for(i=3;i<=NF;i++) {print $i}}' <<<"$input"

由于它不知道我可以给出多少字段,我添加了一个 for 循环直到 NF 并将 RS 更改为空行而不是换行符。