如何避免 Unix 命令中的转义分隔符?

如何避免 Unix 命令中的转义分隔符?

我需要计算以波形符 (~) 分隔的字段的总和。我遇到的问题是我的数据也有分隔符转义。

例子

1~CEO~ashok\~kumar~1000

正如我们在上面的第三个字段中看到的,我们已经转义了我想避免的分隔符。我正在运行以下命令,但它无法处理此问题。

$ cat test.out|awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'

假设test.out数据为:

1~CEO~ashok\~kumar~1000
2~CFO~Ranjan~2000
3~CEO~kumar~1000

所以我的输出应该是 4000。但目前用我的命令我只得到 3000!

答案1

只需在处理之前将转义分隔符更改为其他内容即可awk。这可以通过以下方式完成sed

$ cat test.out| sed 's/\\~/=/g' | \
    awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'
4000

而且,正如通常的情况一样,不需要cat

$ sed 's/\\~/=/g' test.out | awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'

答案2

这是不使用的替代方案awk

$ sed 's/\\~/=/g' test.out | cut -d"~" -f4 | paste -sd+ | bc
4000

上面的代码用于sed交换\~第三列中转义的波形符。然后我们可以使用cut选择第四列数字,然后重建它们,以便它们之间用加号(+)分隔。

$ sed 's/\\~/=/g' test.out | cut -d"~" -f4 | paste -sd+
1000+2000+1000

然后将该字符串提供给二进制计算器,bc对它们进行求和。

答案3

为了处理转义,一般的方法是使用perlor PCRE 及其交替正则表达式运算符与无回溯运算符相结合。这里是 GNU grep

grep -Po '(?>(?:\\.|.)*?~){3}\K(?:\\.|[^~])*' << \EOF
1~CEO~ashok\~kumar~1000
2~CFO~Ranjan~2000
3~CEO~kumar~1000
4~field2~field3\\~10000~field5-note-the-escaped-backslash-not-tilde
5~a\~b\~c\~no-4th-field-here
EOF

这使:

1000
2000
1000
10000

(您可以将其与平时相加awk '{s+=$0};END{print s}')。

使用 GNU sed,您还可以这样做:

sed -rn 's/((\\.|[^\~])*~){3}((\\.|[^~])*).*/\3/p'

使用 GNU awk,您可以FPAT将字段定义为转义字符或非波形符或反斜杠字符的序列:

awk -v FPAT='(\\\\.|[^\\\\~])*' '{print $4}'

答案4

这在 awk 中有点笨拙(除非您可以预处理源代码来更改分隔符,但这需要知道另一个不能出现在输入中的字符或字符序列)。您可以做的一件事是读取整行,然后修改该行以获取换行符作为分隔符(换行符是不可能出现在一行中的一件事)。

awk 'BEGIN {FS="\n"}
{
    gsub("~", "\n");
    gsub("\\\n", "~");
    gsub("\\\\", "\\");
    $0 = $0;
    print $4;
}'

相关内容