使用 awk 格式化文件

使用 awk 格式化文件

我的输入文件包含以下格式的数据:

1503668542862176    manager=10001|Bounced=999|Analyst=10004|Business Analyst=10005|Programmer=10003
1552024948590636    manager=10001|Bounced=999|Analyst=10004
1551728916565460    Bounced=999|Analyst=10004
1553617087089790    Analyst=10004
1538058487418963    manager=10001|Architect=10002|Analyst=10004

我必须转换第二列,其中每对都key=value应该用双引号引起来,"key"="value"并且应该使用以下内容|替换为。,awk

1503668542862176    "manager"="10001","Bounced"="999","Analyst"="10004","Business Analyst"="10005","Programmer"="10003"
1552024948590636    "manager"="10001","Bounced"="999","Analyst"="10004"
1551728916565460    "Bounced"="999","Analyst"="10004"
1553617087089790    "Analyst"="10004"
1538058487418963    "manager"="10001","Architect"="10002","Analyst"="10004"

答案1

$ sed -e 's/|/","/g' -e 's/=/"="/g' -e 's/\t/\t"/' -e 's/$/"/' input.txt

这会:

  • 将任何替换|,
  • 将任何替换="="
  • 将第一个制表位替换为\t"
  • 追加 a"和行尾

最简单的方法awk是更改​​为字段分隔符:

$ awk -v FS="|" -v OFS='","' '{$1=$1}1' \
  | awk -v FS="=" -v OFS='"="' '{$1=$1}1'\
  | awk -v FS="\t" '{print $1,"\""$2"\""}' input.txt

答案2

使用 sed:

sed -e 's/|/","/g;s/=/"="/g;s/ /"/4;s/$/"/g' file

1503668542862176   "manager"="10001","Bounced"="999","Analyst"="10004","Business Analyst"="10005","Programmer"="10003"
1552024948590636   "manager"="10001","Bounced"="999","Analyst"="10004"
1551728916565460   "Bounced"="999","Analyst"="10004"
1553617087089790   "Analyst"="10004"
1538058487418963   "manager"="10001","Architect"="10002","Analyst"="10004"

答案3

如果您可以使用 GNU awk(通常在任何标准 Linux 发行版上都可用),则可以将子表达式与函数一起使用gensub() :

< input_data awk -- '{gsub("\\|", ","); print gensub("([[:alpha:]][^=]*)=([^,]+)", "\"\\1\"=\"\\2\"", "g")}'

假设|仅作为键值对分隔符出现,则首先gsub()将每个值转换为|in ,,然后该gensub()函数执行其余的操作。

如果您必须使用 POSIX awk,那么您仍然可以使用一系列(确实很尴尬......)的单个脚本获得相同的结果gsub()

< input_data awk -- '{gsub("=", "\""); gsub("([[:alpha:]][^\"]*)", "\"&\"="); gsub("\"[^|]*", "&\""); gsub("\\|", ","); print;}'

分解(仅awk脚本部分):

{
    gsub("=", "\"");
    gsub("([[:alpha:]][^\"]*)", "\"&\"=");
    gsub("\"[^|]*", "&\"");
    gsub("\\|", ",");
    print;
}

第一个gsub()将每个替换=为 a ",为随后的几个gsub()s 铺平道路,第一个查找键直到(但不包括)第一个",并将整个字符串替换为前导"加上找到的键加上尾随"=,第二个gsub()查找以"(最初是=)开始直到(但不包括)第一个|(如果存在)的值,并将该字符串替换为其自身加上尾随的"

基本上,第二个解决方案用作"辅助键值分隔符,因此要求它不会出现在键或值中。

最终解决方案gsub()将全部替换|,第一个解决方案。

答案4

通过awk命令完成

命令:

awk '{gsub(/\|/,",",$0);print $0}' filename | awk '{$2="\""$2;print $0}'| awk '{gsub(/\=/,"\"=\"",$0);print $0}'| awk '{gsub(/\,/,"\",\"",$0);print $0}'| awk '{$NF=$NF"\"";print $0}'

输出

 awk '{gsub(/\|/,",",$0);print $0}' filename| awk '{$2="\""$2;print $0}'| awk '{gsub(/\=/,"\"=\"",$0);print $0}'| awk '{gsub(/\,/,"\",\"",$0);print $0}'| awk '{$NF=$NF"\"";print $0}'

1503668542862176 "manager"="10001","Bounced"="999","Analyst"="10004","Business Analyst"="10005","Programmer"="10003"
1552024948590636 "manager"="10001","Bounced"="999","Analyst"="10004"
1551728916565460 "Bounced"="999","Analyst"="10004"
1553617087089790 "Analyst"="10004"
1538058487418963 "manager"="10001","Architect"="10002","Analyst"="10004"

相关内容