是否总是如此,在修改特定字段后awk,输出字段分隔符上的信息会丢失?如果有多个字段分隔符并且我希望它们被恢复会发生什么?
例如,假设我有一个example包含以下内容的简单文件:
a:e:i:o:u
Run Code Online (Sandbox Code Playgroud)
如果我只运行一个awk考虑输入字段分隔符的脚本,它会打印我文件中的每一行,例如运行
awk -F: '{print $0}' example
Run Code Online (Sandbox Code Playgroud)
我会看到原来的一行.但是,如果我直接修改其中一个字段,例如
awk -F: '{$2=$2"!"; print $0}' example
Run Code Online (Sandbox Code Playgroud)
我没有得到原始行的修改版本,而是看到由默认空白分隔符分隔的字段,即:
a e! i o u
Run Code Online (Sandbox Code Playgroud)
我可以通过指定OFS来获取原始版本的修改版本,例如:
awk -F: 'BEGIN {OFS=":"} {$2=$2"!"; print $0}' example
Run Code Online (Sandbox Code Playgroud)
但是,在有多个潜在的场分离器的情况下,但是在多个分离器的情况下,是否有一种简单的方法来恢复原始分离器?
例如,如果example同时使用:和;作为分隔符,我可以-F":|;"用来处理文件,但OFS不足以恢复原始分隔符的相对位置.
更明确地说,如果我们切换到example2包含
a:e;i:o;u
Run Code Online (Sandbox Code Playgroud)
我们可以使用
awk -F":|;" 'BEGIN {OFS=":"} {$2=$2"!"; print $0}' example2
Run Code Online (Sandbox Code Playgroud)
(或-F"[:;]")得到
a:e!:i:o:u
Run Code Online (Sandbox Code Playgroud)
但是我们已经失去了:和; 如果我们能够恢复,那将会得到维持
a:e!;i:o;u
Run Code Online (Sandbox Code Playgroud)
您需要使用GNU awk将第4个arg用于split(),这样可以保存分隔符,就像RT对RS一样:
$ awk -F'[:;]' '{split($0,f,FS,s); $2=$2"!"; r=s[0]; for (i=1;i<=NF;i++) r=r $i s[i]; $0=r} 1' file
a:e!;i:o;u
Run Code Online (Sandbox Code Playgroud)
没有自动填充的FS匹配字符串数组,因为每次将记录拆分为字段时,存储与FS匹配的字符串的时间和内存有多昂贵.相反,GNU awk人员为split()提供了第4个arg,这样你就可以在需要的时候自己动手.这是几年前在经验丰富的awk用户和gawk提供商之间的comp.lang.awk新闻组中进行长时间对话的结果,然后才同意这是最好的方法.
见split()在https://www.gnu.org/software/gawk/manual/gawk.html#String-Functions.