在 Perl 正则表达式中替换 % 标记但不替换 \%

在 Perl 正则表达式中替换 % 标记但不替换 \%

我在想如何替换sed -命令中的[^\]%标记而不是标记\%回答。我认为后视是没有必要的。

我当前的 Sed 命令,但我认为 Perl 在这里是必须的

cat something | sed 's#%.*</#</#'                

这也删除了%符号后面的所有内容,即 LaTeX 中的所有注释,但不删除百分比值。

我不成功的 Perl 尝试

cat something | perl 's#[^\]%.*</#</#'

我不知道如何让 Perl 获取 cat 的标准输出。

数据

------------------------------
Protocol of pre-eclampsia
------------------------------
Monitoring in 90\% cases

Antihypertensives when % this is a comment, please, remove me!
$SBP/DBP > 160/110$; slowly.     
------------------------------

所需输出

------------------------------
Protocol of pre-eclampsia
------------------------------
Monitoring in 90\% cases

Antihypertensives when
$SBP/DBP > 160/110$; slowly.     
------------------------------

你怎么可以替换%标志而不呢\%?如果您可以通过 Sed 做到这一点,请发表评论。

答案1

像许多(如果不是大多数)文本解析工具一样,perl可以从命令行获取输入,因此不需要cat.您只需要-e它可以让您将脚本作为命令行参数传递,-n这意味着“在每行输入上运行脚本”。或者,您可以使用-p开关,这意味着“在每行输入上运行脚本,然后打印该行”。这两个命令是等效的(但第二个命令是 cat 的经典无用用法,请使用第一个):

perl -pe 's/foo/bar/' file
cat file | perl -pe 's/foo/bar/'

现在,如果我理解正确的话,您想要删除所有 LaTeX 注释(尽管这不是您的问题所述)。如果是这样,一个向后看是最简单的方法:

perl -pe 's/(?<!\\)%.*//' file 

你的正则表达式也应该有效,你只需要保留在 之前匹配的字符%并转义反斜杠:

perl -pe 's/(^|[^\\]+)%.*/$1/' file

你可以用 GNU 做同样的事情sed

sed -r 's/(^|[^\\])%.*/\1/' file

答案2

如果你只想替换后面的内容%,而不是后面的内容\%,在 Perl 中,最简单的方法是使用消极回顾%.*:仅当前面没有反斜杠时才匹配。

perl -pe 's/(?<!\\)%.*//'

然而,这不会匹配类似的东西Hello world.\\%wibble。为此,您需要检查 前面是否%有偶数个反斜杠。你不能用lookbehind 来做到这一点,因为Perl 的lookbehind 只支持固定长度的模式。相反,匹配正则表达式中的反斜杠,并使用后向查找来确保正则表达式捕获所有反斜杠。

perl -pe 's/(?<!\\)((?:\\\\)*)%.*/$1/'

您也可以使用不支持lookbehind 的工具来做到这一点。在这种情况下,您需要使用一系列棘手的替换命令,或者匹配反斜杠并将它们复制到替换文本。

sed -e 's/^\(\(\\\\\)*\)%.*/\1/' -e 's/\([^\\]\(\\\\\)*\)%.*/\1/'

请注意,如果您正在处理 LaTeX 文档,则可能需要保留其他百分号,例如在逐字块中。仅使用正则表达式无法完成此操作。

答案3

替换未转义字符的常见习惯用法perl是:

$ printf '%s\n' '% \% \\% \\\%' | perl -pe 's/(\\.)|%/$1||"<replacement>"/ge'
<replacement> \% \\<replacement> \\\%

因此,要删除从未转义开始的所有内容%

perl -pe 's/(\\.)|%.*/$1/g'

如果您sed支持-E(FreeBSD/GNU):

sed -E 's/(\\.)|%.*/\1/g'

或者使用 GNU sed

sed 's/\(\\.\)\|%.*/\1/g'

如果交替 RE 运算符不可用(如标准基本 RE 中),您通常可以使用\{0,1\}

sed 's/\(\(\(\\.\)\{0,1\}[^\\%]*\)*\)\(%.*\)\{0,1\}/\1/'

相关内容