我收到超出我控制范围的输入文件,其中某些列中包含前导单引号,例如
'foo|'012|that's nice|bar
Run Code Online (Sandbox Code Playgroud)
我想从每个字段中删除所有前导单引号,以获得预期的输出:
foo|012|that's nice|bar
Run Code Online (Sandbox Code Playgroud)
使用 awk,我假设 gsub 正则表达式元字符像^
每列一样工作,但它似乎只在行的开头工作:
$ echo "'foo|'012|that's nice|bar" | awk -F'|' '{gsub(/^'\''/,"")}1'
foo|'012|that's nice|bar
Run Code Online (Sandbox Code Playgroud)
如何从每列中删除前导单引号?
不需要awk
,sed
可以这样做:
sed -E "s/(^|\\|)\'/\\1/g"\n
Run Code Online (Sandbox Code Playgroud)\n-E
切换到扩展正则表达式的选项将出现在 POSIX 标准的下一版本中,但大多数实现已经支持sed
。或者您可以使用perl
which 取代sed
and awk
:
perl -pe \'s/(^|\\|)\'\\\'\'/$1/g\'\n
Run Code Online (Sandbox Code Playgroud)\n或者:
\nperl -pe "s/(^|\\|)\\K\'//g"\n
Run Code Online (Sandbox Code Playgroud)\n(\\K
标记K
比赛的开始)。
或者:
\nperl -pe "s/(?<![^|])\'//g"\n
Run Code Online (Sandbox Code Playgroud)\n(\'
只要前面没有除 以外的字符即可进行替换|
)。
或者用它的awk
模式:
perl -F\'\\|\' -pe \'s/^\'\\\'\'// for @F; $_ = join "|", @F\'\n
Run Code Online (Sandbox Code Playgroud)\n使用awk -F\'|\'
,您需要将替换应用于每个字段,就像上面的perl
模式一样awk
:
perl -pe \'s/(^|\\|)\'\\\'\'/$1/g\'\n
Run Code Online (Sandbox Code Playgroud)\n对于awk
,当字段分隔符是单个字符时,作为特殊情况,它不会被视为正则表达式,因此不需要转义|
。
$
inawk
是一个一元运算符,它需要一个数字,如果它是 1 和 之间的数字NF
,则返回相应的字段;如果该数字为 0,则返回整个记录,否则返回空字符串\xc2\xb9。
sub()
并且gsub()
可以采用 2 或 3 个参数,如果未提供第三个参数((唯一的)替换主题),则它默认为整个记录 ( $0
)。与不同的方式与与 不同的方式gsub()
相同。仅替换第一次出现的模式,而替换所有出现的模式。sub()
s/x/y/g
s/x/y/
sed
sub()
gsub()
这里的正则表达式只能匹配一次,因为它是在开始时锚定的,所以sub()
和gsub()
不会产生任何影响。
IOW,gsub()
不是在每个字段中进行一次替换,而是在一个字符串中进行所有替换,默认情况下该字符串是整个未分割的记录。
\xc2\xb9 从技术上讲,它们被视为数字字符串。也就是说,如果它们看起来像数字,否则将被视为数字。空字符串被视为字符串。
\n