使管道分隔文件中的字段无效



当数据字段中有管道时,我无法获得所需的 o/p。

If the i/p is 
SAmple file is tst
hdr1|"hdr2|tst"|"hdr3|tst|tst"|hdr4|"hdr5|tst|tst"
lbl1|"lbl2|tst"|"lbl3|tst|tst"|lbl4|"lbl5|tst|tst"
I tried with this cmd but dont get the expected o/p - cut -f2,3 -d"|" tst
The expected o/p is 
"hdr2|tst"|"hdr3|tst|tst"
"lbl2|tst"|"lbl3|tst|tst"

有没有一种简单的方法可以破解这个 o/p...不想使用 sed,因为正在使用的工具不允许使用字符("-反斜杠)。我的意思是将此命令嵌入到其中一个工具中 我也在使用旧版本的gawk -

so this cmd doesnt give te desired o/p
gawk -v FPAT='[^|]*|("[^"]*")+' '{print $2, $3}' OFS="|"
Output of gawk --version
GNU Awk 3.1.7
Output of cat -vet tst
hdr1|"hdr2|tst"|"hdr3|tst|tst"|hdr4|"hdr5|tst|tst"$
lbl1|"lbl2|tst"|"lbl3|tst|tst"|lbl4|"lbl5|tst|tst"$

升级你的gawk版本是迄今为止最好的方法,因为你缺少一些错误修复和自Gawk 3.1.7在10+年前问世以来引入的大量非常有用的功能(我们目前使用的是gawk版本5.1!),但是如果你由于某种原因不能这样做,那么 - 如果你没有FPAT在每个UNIX机器上的任何shell中使用任何awk,你可以这样做:

$ cat tst.awk
BEGIN { OFS="|" }
{
orig = $0
$0 = i = ""
while ( (orig != "") && match(orig,/[^|]*|("[^"]*")+/) ) {
$(++i) = substr(orig,RSTART,RLENGTH)
orig = substr(orig,RSTART+RLENGTH+1)
}
print $2, $3
}

.

$ awk -f tst.awk file
"hdr2|tst"|"hdr3|tst|tst"
"lbl2|tst"|"lbl3|tst|tst"

只是为了验证它是否正确识别了所有字段:

$ cat tst.awk
BEGIN { OFS="|" }
{
orig = $0
$0 = i = ""
while ( (orig != "") && match(orig,/[^|]*|("[^"]*")+/) ) {
$(++i) = substr(orig,RSTART,RLENGTH)
orig = substr(orig,RSTART+RLENGTH+1)
}
print NF " <" $0 ">"
for (i=1; i<=NF; i++) {
print "t" i " <" $i ">"
}
}

.

$ awk -f tst.awk file
5 <hdr1|"hdr2|tst"|"hdr3|tst|tst"|hdr4|"hdr5|tst|tst">
1 <hdr1>
2 <"hdr2|tst">
3 <"hdr3|tst|tst">
4 <hdr4>
5 <"hdr5|tst|tst">
5 <lbl1|"lbl2|tst"|"lbl3|tst|tst"|lbl4|"lbl5|tst|tst">
1 <lbl1>
2 <"lbl2|tst">
3 <"lbl3|tst|tst">
4 <lbl4>
5 <"lbl5|tst|tst">

如果您没有嵌入双引号,则可以将引号分隔符值替换为另一个未使用的字符(我使用了~),并在提取后切换回原始值。 显然,它要求在文本中不使用新的分隔符。

$ awk 'BEGIN{OFS=FS="""} {for(i=2;i<NF;i+=2) gsub("\|","~",$i)}1' file | 
awk 'BEGIN{OFS=FS="|"}  {print $2,$3}'                                 | 
sed 's/~/|/g' 
"hdr2|tst"|"hdr3|tst|tst"
"lbl2|tst"|"lbl3|tst|tst"

不确定它是否比单个awk脚本简单。

这里的主要问题是文档格式设计。 如果有嵌入的双引号或转义管道等,则需要另一个补丁。

最新更新