Parsing 使管道分隔文件中的字段为空
当数据字段中有管道时,我无法获得所需的o/pParsing 使管道分隔文件中的字段为空,parsing,awk,pipe,delimited,Parsing,Awk,Pipe,Delimited,当数据字段中有管道时,我无法获得所需的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
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 bcoz我使用的工具不允许使用字符(“-反斜杠”)。我的意思是,我将这个命令嵌入到一个工具中
我也在使用老版本的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版本是目前为止最好的方法,因为你错过了一些bug修复和自gawk 3.1.7 10多年前问世以来引入的大量非常有用的功能(我们目前使用的是gawk版本5.1!)但是,如果出于某种原因您无法做到这一点,那么-如果您没有在每个UNIX设备上的任何shell中使用任何awk的
FPAT
,您可以这样做:
$ 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
}
只是为了验证它正确标识了所有字段:
$ 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 ">"
}
}
$cat tst.awk
开始{OFS=“|”}
{
原价=$0
$0=i=“”
while((orig!=“”)和&match(orig,/[^ |]*|(“[^”]*”+/)){
$(++i)=子字符串(起始、起始、长度)
orig=substr(orig,RSTART+RLENGTH+1)
}
打印NF“”
对于(i=1;i如果没有嵌入双引号,则可以用另一个未使用的字符(我使用了~
)替换带引号的分隔符值,并在提取后切换回原始值。显然,这要求在文本中不使用新的分隔符
$ 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'BEGIN{OFS=FS=“\”“}{for(i=2;iLooks to be bug in the GNU awk version your have with use FPAT.根据此评论-,建议将您的gawk升级到4.2+,如果您使用的是FPATIt不是bug,FPAT只是在gawk 4.0之前才被引入,OP在gawk 3.1.7上(已经过时10年了!)@埃德蒙顿:哎呀!我不知道。无论如何,升级到后一个版本是OPS的一个选择。谢谢你回答这个问题。而不是创建(.awk脚本)-是否有任何其他方法可以获得所需的结果,或者我们是否可以有其他方法来解决此问题。我不确定你在问什么,但如果是如何执行awk脚本而不将其存储在一个文件中,该文件只是awk'script'文件
而不是awk-f tst.awk文件
。请参阅awk手册页,然后尝试awk'BEGIN{}打印“你好,世界”}“
如果你不确定我的意思。我明白了。但我的问题是,有没有捷径可以获取o/pYes、更新你的gawk版本和使用FPAT。否则,我想我们会发现你是否得到了更短的答案。@AbdulWahabKhan,请停止从多个论坛中提取答案-已经提出了类似/相同的观点/意见,并找到了解决方案。”已提供。OP表示,无论他们处于何种环境,都不允许他们在脚本中使用反斜杠(我使用的工具不允许使用字符(“-backslash”)
),因此可能需要调整或2。顺便说一句,gsub()的第一个参数
是一个regexp,而不是一个字符串,因此如果使用regexp分隔符,则不需要在转义(gsub(/\\\124;/…
)上加倍
$ 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"