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 更改为空行而不是换行符。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/270655.html