
我正在使用 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