如何反斜杠忽略传递到 cut 的分隔符?

如何反斜杠忽略传递到 cut 的分隔符?

我有以下用例:

echo "some comment char '\;' embedded in strings   ; along with inline comments" \
| cut -d';' -f 1

我想:

some comment char ';' embedded in strings

我得到:

some comment char '

如何隐藏配置为剪切剪切的分隔符,如本用例所示?理想情况下, cut 会读取并尊重反斜杠,但如果不是这样,还有其他方法吗?

答案1

在每个 Unix 机器上的任何 shell 中使用任何 awk:

$ echo "some comment char '\;' embedded in strings   ; along with inline comments" |
awk -F';' '{gsub(/\\\\/,RS); gsub(/\\;/,"\\\\"); gsub(/\\\\/,";",$1); gsub(RS,"\\",$1); print $1}'
some comment char ';' embedded in strings

和借用@Stéphane 的示例输入文件:

$ cat file
foo\;bar;baz
foo\\;bar;baz

$ awk -F';' '{gsub(/\\\\/,RS); gsub(/\\;/,"\\\\"); gsub(/\\\\/,";",$1); gsub(RS,"\\",$1); print $1}' file
foo;bar
foo\

并将其扩展为包含更多字段的行:

$ cat file
foo\;bar;baz
foo\\;bar;baz
foo\\;bar\;this\;that\\;baz;here\;and\;there

我们可以根据需要打印任何或所有字段(这里还首先输出原始行,并在包含单个字段的每个输出行的开头输出字段编号):

$ awk -F';' '{print; gsub(/\\\\/,RS) gsub(/\\;/,"\\\\"); for (i=1; i<=NF; i++) { gsub(/\\\\/,";",$i); gsub(RS,"\\",$i); print "   " i, $i }; print "---" }' file
foo\;bar;baz
   1 foo;bar
   2 baz
---
foo\\;bar;baz
   1 foo\
   2 bar
   3 baz
---
foo\\;bar\;this\;that\\;baz;here\;and\;there
   1 foo\
   2 bar;this;that\
   3 baz
   4 here;and;there

以上:

  1. \\将当前输入行 ( ) 中的每个字符转换$0为换行符( 的默认值RS),换行符是一个不能存在于换行符分隔记录中的字符串,因此我们可以\\;在输入中将其处理为转义的反斜杠而不是转义的半字符冒号,那么
  2. 将每个\;in转换$0\\,它现在也是一个不能存在于 $0 中的字符串,因为我们只是将它们全部转换为RSs,以摆脱;其中的麻烦,然后
  3. 修改操作$0会导致 awk$0在每个剩余的字段中重新拆分为字段;,从而将我们所需的目标字符串放入 中$1,然后
  4. 我们将 every \\(在上面第 2 步创建的)转换$1;,然后
  5. 将 every RS(在上面的步骤 1 创建的)转换$1\\,然后
  6. 我们打印该字段,$1

该方法适用于RSPOSIX 定义的每个文字字符串,如果您RS是某些 awks 支持的正则表达式,例如 GNU awk,则提出一个不带正则表达式元字符的字符串,该字符串与该正则表达式匹配以用作替换的RS

答案2

使用 GNUgrep或兼容的(对于非标准但现在相当常见的-o选项):

grep -Eo '^(\\.|[^\\;])*'

它匹配并输出 0 个或多个 ( )1o的序列,后跟任何单个字符 ( ),该字符涵盖转义但也转义或除和以外的任何字符,位于行的开头 ( )。*\.;\\;^

例子:

$ cat file
foo\;bar;baz
foo\\;bar;baz
$ grep -Eo '^(\\.|[^\\;])*' file
foo\;bar
foo\\

要删除转义,请通过管道传输到,或者如果您也支持该选项sed 's/\\\(.\)/\1/g',则执行整个操作:sedsed-E

$ sed -E 's/^((\\.|[^\\;])*).*/\1/; s/\\(.)/\1/g' file
foo;bar
foo\

或者与perl

$ perl -lpe 's/^(\\.|[^;])*+\K.*//; s/\\(.)/$1/g' file
foo;bar
foo\

1 但请注意,grep -o不会输出空匹配项。

相关内容