关于 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 并将其视为新行。帮助我如何从给定的输入格式打印两个字段(保留新行)。

  • 字段数是固定的吗?您对@tripleee 的评论暗示不是。我问的原因是,否则似乎没有字段分隔符。在您的第一个示例中,您在字段之间显示分号,但在第二个示例中,您显示换行符。如果换行符是字段分隔符,而您不知道有多少个字段,那么如何判断一个字段何时结束,下一个字段何时开始?
  • @cdarke 输入有 “;” 作为分隔符,我现在必须将其转换为用新行分隔的输出,同时还要保留原始换行符。如您所见,Field1、Field2 位于彼此下方,因此与多少字段无关。例如,字段 1:xxx \\\\
    yyy 字段 2:zzzz \\\\
    aaaa 它应该打印 xxx \\\\
    年年 \\\\
    zzzz \\\\
    啊啊啊
  • 啊,好的,所以输入字段分隔符是分号。


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

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
  • $0 = r 意味着什么?如果输入可以有多个字段 FIELD1,FIELD2,FIELD3 而我们不能确定有多少呢?
  • 赋值 $0 = r ORS $0 将当前行粘合到 r 的末尾,前面有一个换行符,并重新计算字段计数;所以我们在 r 中收集行,直到它包含四个字段。
  • 如果您不知道有多少字段并且其中一些可能包含换行符,则无法解析您的数据,因为格式不明确。也许有例如一种允许我们识别最后一个字段中的第一个的模式,但是根据您提供的信息,您的问题无法解决可变字段长度的问题。
  • 如果您在打开文件时以某种方式知道有多少字段,则可以使用 awk -v f=4 ‘… NF<f { next } …}
  • …虽然如果您知道您的输入恰好是一条记录,那么它又很容易。我写这个答案的假设是你有一个分号分隔的输入文件,它可能包含多个记录,但如果它总是正好是一个,那应该是合理的。


单个 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 一次读取一行。
  • @anubhava 如果两个换行符在一起,那仍然会中断。
  • IMO 任何 CSV 都必须定义记录分隔符。相同的 \
    不能作为记录分隔符并出现在未引用的单元格值中。
  • 我尝试了相同的命令,复制粘贴,它不起作用,我得到 Sno;Name;Field1-Foo;Field2 和下一行: FIELDS ALOOCATED
  • 我刚走出去。一旦我在 40 分钟内回来,将为您提供一个工作演示。
  • FPAT 仅在 gnu-awk 4.0 中可用,可能 op 没有它。
  • 检查这个工作演示但是你应该 awk 版本 4 及更高版本才能使用 FPAT


只需更改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>
  • 为什么 field2 末尾有一个额外的换行符?
  • 不确定它是 here-doc 还是 awk,但好点(编辑)。
  • 它不是这里的字符串。必须是awk。
  • 在您的帮助下我得到了解决方案,谢谢,但是我做的有点不同


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 更改为空行而不是换行符。


来源:https://www.codenong.com/38260214/

微信公众号
手机浏览(小程序)

Warning: get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(): Failed to enable crypto in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(https://static.shanhubei.com/qrcode/qrcode_viewid_9919.jpg): failed to open stream: operation failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57
0
分享到:
没有账号? 忘记密码?