perl:用包含新行(换行符)的变量替换字符串

perl:用包含新行(换行符)的变量替换字符串

我想进行包含元字符的编辑。这里https://stackoverflow.com/questions/29613304/is-it-possible-to-escape-regex-metacharacters-reliously-with-sed解决方案之一是通过perlwith s\Q ... \E(已接受答案的近端)。据说它可以处理多线,但是:

echo 'a-b' > a.txt;from='-';to='\n';perl -s -0777 -pe 's/\Q$from\E/$to/' -- -from="$from" -to="$to" a.txt
a\nb
echo 'a-b' > a.txt;from='-';to='\n';perl -s -0777 -pe 's/\Q$from\E/\n/' -- -from="$from" -to="$to" a.txt
a
b

仅当我将其写入自身时,我才能用换行符替换s,通过变量,它由于某种原因不起作用。我无法通过网络搜索找到答案。如何让它与\n变量一起工作?

\nPS 变量可以是任意长度并包含任何元字符,除了用换行符替换的一个特定字符序列(例如 )之外,所有这些字符都按字面意思使用。

答案1

正确的方法,问题不在于Perl,而在于shell

echo 'a-b' > a.txt
from='-'
to=$'\n' # <<< look at this
perl -s -0777 -pe 's/\Q$from\E/$to/' -- -from="$from" -to="$to" a.txt

输出

a
b

答案2

我想我已经找到了一种通过以下方式预处理变量来分两步完成此操作的方法:

to="$(printf "%s" "${to}" | perl -pe 's/\Q\n\E/\n/g')"

令人惊讶的是,这不适用于单个符号(换行)替换,但适用于较长的字符串:

echo 'a-b' > a.txt;from='-';to='\n';to="$(printf "%s" "${to}" | perl -p -e 's/\Q\n\E/\n/g')";perl -s -0777 -pe 's/\Q$from\E/$to/' -- -from="$from" -to="${to}" a.txt
ab
echo 'a-b' > a.txt;from='-';to='\nd';to="$(printf "%s" "${to}" | perl -p -e 's/\Q\n\E/\n/g')";perl -s -0777 -pe 's/\Q$from\E/$to/' -- -from="$from" -to="${to}" a.txt
a
db

现在我确实只有更长的字符串,但我想知道为什么它对于单个符号失败。

它在从文件读取变量赋值时起作用,如下所示:

itext="${line}"
itext="$(printf "%s" "${itext}" | perl -p -e 's/\Q\n\E/\n/g')"
while read -r line; do
    otext="${line}"
    otext="$(printf "%s" "${itext}" | perl -p -e 's/\Q\n\E/\n/g')"
    perl -s -0777 -pi -e 's/\Q$itext\E/$otext/' -- -itext="${itext}" -otext="${otext}" "${file_to_edit}"
done < "${file_with_edits}"

相关内容