使用 awk 在每个 header 列前加上字符串前缀
prefix every header column with string using awk
我有一堆大的 csv,我想在每个 header 列前加上固定字符串。每个文件都有500多列。
假设我的 header 是:
number;date;customer;key;amount
我试过这条 awk 行:
awk -F';' 'NR==1{gsub(/[^a-z_]/,"input_file.")} { print }'
但我得到(注意第一列缺少前缀并且分隔符已删除):
numberinput_file.dateinput_file.customerinput_file.keyinput_file.amount
预期输出:
input_file.number;input_file.date;input_file.customer;input_file.key;input_file.amount
您的 gsub
会粗暴地将输入中任意位置的非字母字符替换为前缀 - 包括您的列分隔符。
print
可以缩写为脚本最后的常用习语 1
;这只是表示“此条件为真;对每一行执行默认操作(即全部打印)”,尽管这只是风格上的更改。
awk -F';' 'NR==1{
sub(/^/, "input_file."); gsub(/;/, ";input_file."); }
1' filename
如果您想对多个文件执行此操作,可能会在其周围放置一个 shell 循环。如果您只想将所有内容连接到标准输出,您可以一次性将所有文件提供给 Awk(在这种情况下,您可能不想在第一个文件之后打印任何文件的 header 行;也许改变1
到 NR==1 || FNR != 1
).
我会按照以下方式使用 GNU AWK
,令 file.txt
内容为
number;date;customer;key;amount
1;2;3;4;5
6;7;8;9;10
然后
awk 'BEGIN{FS=";";OFS=";input_file."}NR==1{="input_file." }{print}' file.txt
输出
input_file.number;input_file.date;input_file.customer;input_file.key;input_file.amount
1;2;3;4;5
6;7;8;9;10
说明:我将 OFS
设置为 ;
后跟前缀。然后在第一行中,我将前缀添加到第一列,这会触发字符串重建。没有在任何其他行中进行任何修改,因此它们 print
按原样编辑。
(在 GNU Awk 5.0.1 中测试)
在任何 awk 中都是:
$ awk 'NR==1{gsub(/^|;/,"&input_file.")} 1' file
input_file.number;input_file.date;input_file.customer;input_file.key;input_file.amount
但是 sed 的存在是为了进行这样的简单替换,例如使用具有 -E
的 sed 来启用 ERE(例如 GNU 和 BSD sed):
$ sed -E '1s/^|;/&input_file./g' file
input_file.number;input_file.date;input_file.customer;input_file.key;input_file.amount
如果您使用的是 GNU 工具,那么您可以使用以上任一方法通过以下任一方法一次性更改所有 CSV 文件:
awk -i inplace 'NR==1{gsub(/^|;/,"&input_file.")} 1' *.csv
sed -i -E '1s/^|;/&input_file./g' *.csv
还有 awk
使用 for
循环和 printf
:
awk 'BEGIN{FS=OFS=";"} NR==1{for (i=1; i<=NF; i++) printf "%s%s", "input_file." $i, (i<NF ? OFS : ORS)}' file
input_file.number;input_file.date;input_file.customer;input_file.key;input_file.amount
我有一堆大的 csv,我想在每个 header 列前加上固定字符串。每个文件都有500多列。
假设我的 header 是:
number;date;customer;key;amount
我试过这条 awk 行:
awk -F';' 'NR==1{gsub(/[^a-z_]/,"input_file.")} { print }'
但我得到(注意第一列缺少前缀并且分隔符已删除):
numberinput_file.dateinput_file.customerinput_file.keyinput_file.amount
预期输出:
input_file.number;input_file.date;input_file.customer;input_file.key;input_file.amount
您的 gsub
会粗暴地将输入中任意位置的非字母字符替换为前缀 - 包括您的列分隔符。
print
可以缩写为脚本最后的常用习语 1
;这只是表示“此条件为真;对每一行执行默认操作(即全部打印)”,尽管这只是风格上的更改。
awk -F';' 'NR==1{
sub(/^/, "input_file."); gsub(/;/, ";input_file."); }
1' filename
如果您想对多个文件执行此操作,可能会在其周围放置一个 shell 循环。如果您只想将所有内容连接到标准输出,您可以一次性将所有文件提供给 Awk(在这种情况下,您可能不想在第一个文件之后打印任何文件的 header 行;也许改变1
到 NR==1 || FNR != 1
).
我会按照以下方式使用 GNU AWK
,令 file.txt
内容为
number;date;customer;key;amount
1;2;3;4;5
6;7;8;9;10
然后
awk 'BEGIN{FS=";";OFS=";input_file."}NR==1{="input_file." }{print}' file.txt
输出
input_file.number;input_file.date;input_file.customer;input_file.key;input_file.amount
1;2;3;4;5
6;7;8;9;10
说明:我将 OFS
设置为 ;
后跟前缀。然后在第一行中,我将前缀添加到第一列,这会触发字符串重建。没有在任何其他行中进行任何修改,因此它们 print
按原样编辑。
(在 GNU Awk 5.0.1 中测试)
在任何 awk 中都是:
$ awk 'NR==1{gsub(/^|;/,"&input_file.")} 1' file
input_file.number;input_file.date;input_file.customer;input_file.key;input_file.amount
但是 sed 的存在是为了进行这样的简单替换,例如使用具有 -E
的 sed 来启用 ERE(例如 GNU 和 BSD sed):
$ sed -E '1s/^|;/&input_file./g' file
input_file.number;input_file.date;input_file.customer;input_file.key;input_file.amount
如果您使用的是 GNU 工具,那么您可以使用以上任一方法通过以下任一方法一次性更改所有 CSV 文件:
awk -i inplace 'NR==1{gsub(/^|;/,"&input_file.")} 1' *.csv
sed -i -E '1s/^|;/&input_file./g' *.csv
还有 awk
使用 for
循环和 printf
:
awk 'BEGIN{FS=OFS=";"} NR==1{for (i=1; i<=NF; i++) printf "%s%s", "input_file." $i, (i<NF ? OFS : ORS)}' file
input_file.number;input_file.date;input_file.customer;input_file.key;input_file.amount