这是输入字符串:
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;
这里有一个设置OFS
和FS
,然后使用$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++)'