我有如下文件..
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"
"Field1"|"Field2
continue on line 2
continue on line 3"|"Field3"|"ufghjkrtyrtyfgh$"
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"
我正在寻找如下的输出
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"
"Field1"|"Field2continue on line 2continue on line "|"Field3"|"ufghjkrtyrtyfgh$"
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"
- 每条记录将以
$"
- 字段 2 可以分布在多行中
- 文件以竖线分隔并用双引号括起来。
你能帮我解决这个问题吗?
答案1
$ awk '/[$]"[[:space:]]*$/{print;next} {printf "%s",$0}' file
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"
"Field1"|"Field2continue on line 2continue on line 3"|"Field3"|"ufghjkrtyrtyfgh$"
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"
怎么运行的
/[$]"[[:space:]]*$/{print;next}
对于以 结尾的任何行
$
,"
后面可以跟空格,这将 (1) 打印该行,并且 (2) 跳过剩余命令并告诉 awk 从该next
行重新开始。在 awk 正则表达式中,
$
表示行尾。如果我们想匹配一个实际的美元符号,我们必须以某种方式对其进行转义。对其进行转义的最可靠方法是将其放在方括号中:[$]
。在上面的正则表达式中,[$]
后面跟着双引号"
,后面跟着[[:space:]]*
。字符类[[:space:]]
匹配任何空格字符,意味着*
我们应该匹配零个或多个。后面跟着未转义的字符$
,它匹配行尾。printf "%s",$0
对于任何其他行,这将告诉 awk 打印该行没有换行符。
答案2
echo '"Field1a"|"Field2a"|"Field3a"|"ufghjkrtyrtyfgh$"
"Field1b"|"Field2b
continue on line 2
continue on line 3"|"Field3b"|"ufghjkrtyrtyfgh$"
"Field1c"|"Field2c"|"Field3c"|"ufghjkrtyrtyfgh$"' | sed -nr '/^".*"$/{p;n};:a;/[^"]$|^[^"]/{N;s/(.)\n(.)/\1\2/;ta};p'
"Field1a"|"Field2a"|"Field3a"|"ufghjkrtyrtyfgh$"
"Field1b"|"Field2bcontinue on line 2continue on line 3"|"Field3b"|"ufghjkrtyrtyfgh$"
"Field1c"|"Field2c"|"Field3c"|"ufghjkrtyrtyfgh$"
sed 解决方案。以“”开头和结尾的每一行都将被打印,然后 'n' 命令读取下一行并开始新的循环。如果一行不是以“”开头或结尾,它将进入循环 ':a .... ta',然后 'N' 命令附加下一行,'s' 命令将“lastchar”“newline”“firstchar”替换为“lastchar”“firstchar”('(.)\n(.)' 部分),然后只有当 's' 命令实际替换某些内容时(这是循环),'ta' 命令才会跳转到“:a”标记。如果 's' 没有替换任何内容,'ta' 不会跳转到标记,sed 会“打印”结果行并从下一行开始新的循环。awk 解决方案确实看起来干净得多。我认为我的 sed 解决方案可以改进。
编辑:-n 选项抑制自动 sed 输出,因此我们只用“p”打印我们想要的内容。-r 选项用于高级正则表达式。
答案3
稍微不同的 GNUawk
解决方案:
awk -v RS='\\$" *' '{gsub(" *\n", ""); print $0 RT }' file
这使用正则表达式作为记录分隔符。