提问人:WGroleau 提问时间:10/25/2023 最后编辑:WGroleau 更新时间:11/4/2023 访问量:143
如何解决perl替换中的失败?
How to resolve failures in perl substitutions?
问:
一个工作了一段时间的脚本最近停止工作,没有任何更改。诊断消息给人的印象是错误在perl中,因为它们引用了不在我的脚本中的代码!perl 可执行文件的日期为 10 月 6 日,大约是我第一次注意到错误的时候。
寻找解决此问题的任何建议。
~/bin/TC
是用于清理文本格式的脚本:
#!/bin/zsh
perl -p -i -e 's:\r::g;
s:(.*):<p>\1</p>:g;
s:<p></p>::g;
s:\':’:g;
s:([\x27"]?[.?!][\x27"]?) :\1 :g;
s:((”)?[.?!](”)?) :\1 :g;
s:((’)?[.?!](’)?) :\1 :g;
s:((»)?[.?!](»)?) :\1 :g;
s:\*::g;
s: - :—:g;
s:- ::g;
s:([.?!])’” :\1’” :g;
s:([.?!])”’ :\1”’ :g;' $1
以下是最新的调用和结果:
WGroleau@MBP 013 % TC nl_parallel.txt
-i used with no filenames on the command line, reading from STDIN.
Scalar found where operator expected (Missing operator before "$!"?) at -e line 5, near ";}continue{print or die qq(-p destination: $!"
(Might be a runaway multi-line :: string starting on line 4)
syntax error at -e line 5, near ";}continue{print or die qq(-p destination: $!"
Execution of -e aborted due to compilation errors.
/Users/WGroleau/bin/TC:7: unknown file attribute: ?
显然,命令行上有一个文件名。而且,虽然第四行有一个引号,但它是转义的,所以它实际上没有开始字符串。第五行或任何其他行中没有“继续”。第七行的参考对我来说毫无意义。
当脚本工作时,第四行的引文没有被转义。在显示诊断失败后(在不同的文件上多次),我添加了反斜杠,但它仍然给出相同的消息。
Perl 5,版本 38,Subversion 0 (v5.38.0),为 darwin-thread-multi-2level 构建 macOS 14.0 (23A344)
我没有确切记录错误开始的时间,但大约是在 macOS、perl 和 zsh 更新的几周内——9 月底和 10 月初。
答:
\
在 shell 单引号文字中并不特别。
#!/bin/sh
# Start of quoted part
# |
# v
perl -p -i -e 's:\r::g;
s:(.*):<p>\1</p>:g;
s:<p></p>::g;
s:\':’:g;
# ^ ^
# | |
# End of quoted part End of shell command
s:([\x27"]?[.?!][\x27"]?) :\1 :g;
s:((”)?[.?!](”)?) :\1 :g;
s:((’)?[.?!](’)?) :\1 :g;
s:((»)?[.?!](»)?) :\1 :g;
s:\*::g;
s: - :—:g;
s:- ::g;
s:([.?!])’” :\1’” :g;
s:([.?!])”’ :\1”’ :g;' $1
# ^
# |
# Desired end of quoted part
修复:在 shell 脚本的第六行替换为。\'
'\''
(请注意,(与之前捕获的文本匹配的正则表达式原子)应该是替换表达式中的(包含之前捕获的文本的变量)。Perl 会警告你这一点。\1
$1
有了这个错误,你最终会把以下程序传递给:perl
s:\r::g;
s:(.*):<p>\1</p>:g;
s:<p></p>::g;
s:\:’:g
正如你所看到的,你在第四行有一个未终止的。s:::
但用以下内容包装您的代码:-p
LINE: while (<>) {...;}continue{print or die qq(-p destination: $!\n);}
您原本未终止的 被 终止 应该是一个错误消息。s:::
:
这解释了令人困惑的错误消息,但它是正确的,因为它是“从第 4 行开始的失控多行 :: 字符串”。
评论
'\''
s:':’:g;
s:\':’:g;
s:\:’:g;
评论
zsh
s::
/bin/sh