使用 PCRE 进行 sed (如 grep -P)

使用 PCRE 进行 sed (如 grep -P)

我很高兴该选项grep支持 Perl 兼容正则表达式-P

sed该工具没有此功能的原因是什么?

答案1

解决方法:

您可以使用 Pathological Eclectic Rubbish Lister:

perl -pe 's/../../g' file

或内联替换:

perl -i -pe 's/../../g' file

这适用于我使用的情况sed。如果事情变得更加复杂,我会编写一个小的python脚本。

顺便说一句,我换到了无需 Shell 脚本

答案2

对于 GNU Sed 来说,陈述理由似乎

我担心它会落入其中一个“裂缝”......虽然从当时的说法来看,部分工作已经完成,看起来就像是文档和包装的问题......(不过,我承认,在计算机科学领域,最后 10% 的工作往往要花费 90% 的时间......

GNU 错误报告日志 - #22801 已提交变更的状态:升级“sed”RE 以包含 perlRE 语法- 或搜索sed-devel 档案如果您想了解更多详细信息,请搜索“PCRE”。

不要忘记,您可以将perl它用于许多可能想要使用 PCRE 的简单的单行代码中sed

答案3

随着我的替换需求变得越来越复杂,使用perl -pe变得比 更可取sed -e。特别是,能够使用perl 字符类量词比我需要克服的困难更简洁sed

journalctl -u auditd -S 'yesterday' |\
  perl -pe 's/^(\w{3} \d{2} \d{2}:\d{2}:\d{2}) ([\w-]+) audispd/$1 generic-hostname audispd/;
      s/node=[\w-]+/node=generic-hostname/;'

对比

journalctl -u auditd -S "yesterday" |\
  sed -e 's/^\([[:alpha:]]\{3\} [[:digit:]]\{2\} [[:digit:]]\{2\}:[[:digit:]]\{2\}:[[:digit:]]\{2\}\) \([[:alpha:]-]\+\) audispd/\1 generic-hostname audispd/;
      s/node=\([[:alpha:]-]\+\) /node=generic-hostname /;'

我可以使用[0-9]而不是[[:digit:]][A-Za-z]而不是[[:alpha:]],但是 a) 它们都比 perl 等效项长,并且 b)[A-Za-z]将匹配非 ASCII 字符,就像 perl 等效项一样。

bosses-r-dum> echo 'å' | sed -e 's/[A-Za-z]/X/'
å
bosses-r-dum> echo 'å' | perl -CS -pe 's/\w/X/'
X
bosses-r-dum> 

如果您必须处理 unicode,那么能够添加标志并让事情“正常工作”非常方便。我倾向于有机地发展我的正则表达式,因此对“简单”和“复杂”正则表达式使用相同的工具是有意义的,因为如果/当需求发生变化并且我不需要进行任何工具更改(将所有[x]\{#\}实例更改为[x]{#}等),我的“简单”正则表达式可以轻松变成“复杂”正则表达式。

答案4

我个人发现用 Python 做这件事比用 Perl 或 Sed 做起来更容易。

cat file \
| python3 -c 'import sys, re; s = sys.stdin.read(); s=re.sub(r"regex", "replace string", s); print(s);' \
| sudo tee file

完整示例

# add quay and docker registries to approved cri-o registries
cat /etc/crio/crio.conf \
| python3 -c 'import sys, re; s = sys.stdin.read(); s=re.sub(r"#registries\s+\=\s+\[\n#\s+\]", "registries = [\"docker.io\",\"quay.io\"]", s); print(s);' \
| sudo tee /etc/crio/crio.conf

相关内容