如何包含第二个awk以避免awk|awk



这是输入字符串:

status=N&Cau=1&Litrs=0&Freq=0&Min=0

这是提取值并解析为csv的awk:(这很有效,但可能会更好。(

awk 'BEGIN {FS="&"}{for (i=1;i<=NF;i++) print $i}' | awk 'BEGIN {FS="="} {printf("%s;"),$2}'

结果是:

N;1;0;0;0;

问题是:有没有办法在一个awk中做到这一点?(非awk|awk(

CSV中的第一行是:

awk 'BEGIN {FS="&"}{for (i=1;i<=NF;i++) print $i}' | awk 'BEGIN {FS="="} {printf("%s;"),$1}'
status;Cau;Litrs;Freq;Min;

这里有一个设置OFSFS,然后使用$1=$1技巧重建$0,最后进行一点按摩,将第一个;移动到最后。

awk 'BEGIN { OFS=";"; FS="(^|&)[^&]*=" } { $1=$1; print substr($0,2)";" }'
N;1;0;0;0;

我的意思是。。。你可以做一些类似的事情:

awk -F'&' '
{
for (i=1; i<=NF; i++) {
split($i, x, "=")
values[i]=x[2]
}

for (i=1; i<=length(values); i++) {
printf "%s;", values[i]
}
}
'

但我不知道这是否有多大的改善!

如果您的输入只有一行——看起来可能是因为您正在解析URL——您可以使用以下命令:

awk 'BEGIN {FS="="; RS="&"} {sub(/n$/,"",$2); printf "%s;", $2} END {printf "n";}'

这就认识到,输入只是以不同于换行符和空格的方式分隔的记录和字段——因此,通过将字段分隔符更改为=,将记录分隔符改为&,每个xx=N段都被处理为一个单独的行,其中$2等于N。因此,我们只需为每条记录打印$2,后跟分号。但是,如果您在输入行的末尾有一个换行符,您可能会这样做,这会破坏最后一条记录,这就是为什么需要sub(/n$/,"",$2);,删除任何换行符。END子句提供了一个结束换行符。

听起来想要的结果是一组2行的输出:

status;Cau;Litrs;Freq;Min;             # header record
N;1;0;0;0;                             # data record

使用单个awk调用(以取代当前4个awk调用的集合(的一个想法是:

indat="status=N&Cau=1&Litrs=0&Freq=0&Min=0"    # assuming OP has data in a variable
awk -F'[&=]' '                                 # define "&" and "=" as input field separators
{ for (i=1 ; i<NF ; i=i+2)                # loop through the odd numbers
{ hdr=hdr $(i) ";"                  # build header record from odd # fields
dat=dat $(i+1) ";"                # build data record from even # fields
}
}
END  { printf "%sn%sn", hdr, dat }           # dump our 2 records to stdout
' <<< "${indat}"                               # feed input variable via a here string

这将生成:

status;Cau;Litrs;Freq;Min;
N;1;0;0;0;

如果(最终(意图是用几行数据构建CSV文件(例如,输入将来自解析的URL流(,那么在FNR==1时构建/打印hdr变量应该不会太难;此外,我们希望a(在for循环之前清除dat,并且b(在for循环之后打印dat;等等等等。。。

我略微增强了jas提出的解决方案。现在,语法将在前面自行解析分隔符,而在后面则缺少分隔符。它也不需要使用gensub((,所以它完全兼容mawk(或者任何sub/gsub(

尽管所有这些正则表达式都需要对所有4个主要变量进行显式声明,但所有的处理都已经在那里完成了,再加上$1=$1的技巧。

mawk 'BEGIN { FS = "&[^=]+="; OFS = ";"; RS = "^[^=]+=|n"; ORS = ";n"; } ( $1 = $1 )'

对于双线解决方案,它是技巧的组合:

mawk 'BEGIN { OFS = ";"; FS = "=[^&]*(&|$)"; } 
{ save0 = $0; sub(/^[^=]+=/, "", save0); } 
{ $1 = $1; print; }
{ FS = "&[^=]+="; $0 = save0; } (NF++)'

(从技术上讲,没有必要把它们分成{}组,我只是这样写,这样更容易阅读(

为了使其对多行友好,请在接近尾声时更新FS,如

mawk 'BEGIN { OFS = ";"; FS = "=[^&]*(&|$)"; } 
{ save0 = $0; sub(/^[^=]+=/, "", save0); } 
{ $1 = $1; print; }
{ FS = "&[^=]+="; $0 = save0; FS="=[^&]*(&|$)"; } (NF++)'

相关内容

最新更新