我正在使用 perl 来解析许多多语言文本文件。我需要更改两种模式之间的文本:
期望的改变
例如,英文原版是这样的:
\label{whatever}
\ref{whatever}
\autoref{whatever}
{
但和之间的内容}
应以适当的 ISO 639 语言代码作为后缀,例如
\label{whatever_de}
\ref{whatever_de}
\autoref{whatever_de}
测试假设
给定以下文件:
da/myfile_da.tex
de/myfile_de.tex
el/myfile_el.tex
en/myfile_en.tex
每个文件包含:
\label{some_nice_thing}
\ref{some_nice_thing}
\autoref{some_nice_thing}
我的方法
我可以使用文件夹名称作为 ISO 639 代码,并创建一个简单的文件循环。以下内容应该简单地将更改的行打印到终端控制台。我将尝试通过示例解释我得到的特殊结果:
在职的:\\label\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\label\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
不工作:\\ref\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\ref\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
不工作:\\autoref\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\autoref\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
请注意,grep -Pr
适用于每种情况(当然,删除组)
答案1
\\
变成\
双引号。\\ref
变为 ,其后\ref
实际上是。使用四个反斜杠:\r
ef
for f in *; do
if [[ -d $f ]]; then
perl -ne "print if s/(\\\\ref\{.*?)\}/\1_$f\}/g" $f/SystemRequirements_$f.tex
fi
done
同样,\a
是 BELL 字符 ( \x07
)。
答案2
这是一个引用问题。您对变量使用双引号$f
,但双引号还有其他含义。特别是,它们允许对字符进行反斜杠转义,因此当它到达 Perl 时\\
就会变成:\
$ printf "%s\n" "print if s/(\\label\{.*?)\}/\1_$f\}/g"
print if s/(\label\{.*?)\}/\1_\}/g
这会产生一个问题r
,因为\r
将被视为返回字符(请参阅perlrebackslash
) - 它不会匹配r
。使用单引号代替,只为变量打开:
$ printf "%s\n" 'print if s/(\\label\{.*?)\}/\1_'"$f"'\}/g'
print if s/(\\label\{.*?)\}/\1_\}/g