[英]sed copy substring in following line
我有一個.po 文件,如果 msgstr 為空,我需要將 msgid 值復制到 msgstr 值中。
例如
msgid "Hello"
msgstr ""
msgid "Dog"
msgstr "Cane"
應該成為
msgid "Hello"
msgstr "Hello"
msgid "Dog"
msgstr "Cane"
目前,出於測試目的,我正在使用另一個文件,但最終腳本將內聯工作。
#!/bin/bash
rm it2.po
sed $'s/^msgid.*/&\\\n---&/' it.po > it2.po
sed -i '/^msgstr/d' it2.po
sed -i 's/^---msgid/msgstr/' it2.po
這個腳本有兩個問題(至少):
任何幫助,將不勝感激。 提前致謝。
您可以考慮使用更好的工具gnu awk
而不是sed
:
awk -i inplace -v FPAT='"[^"]*"|\\S+' '$id != "" && $1 == "msgstr" && (NF==1 || $2 == "\"\"") {$2=id} $1 == "msgid" {id=$2} 1' file
msgid "Hello"
msgstr "Hello"
msgid "Dog"
msgstr "Cane"
-v FPAT='"[^"]*"|\\S+'
使帶引號的字符串或任何非空白字段成為單個字段。
更易讀的形式:
awk -i inplace -v FPAT='"[^"]*"|\\S+' '
$id != "" && $1 == "msgstr" && (NF==1 || $2 == "\"\"") {$2=id}
$1 == "msgid" {id=$2}
1' file
使用 GNU awk
並僅顯示示例,我們可以嘗試以下操作。
awk -v RS='"[^"]*"|\n+' '
RT=="\n"{ next }
$0~/^msgstr/{
if(RT=="\"\""){ $0=$0 val }
else { $0=$0 RT }
}
$0~/^msgid/ { val=RT
$0=$0 RT }
RT
' Input_file
第二種解決方案:與上述解決方案略有不同,上面只需要出現 1 或 2 次"
,但這將一直有效,直到新行來自第一次出現"
,然后以下將有所幫助,再次編寫並使用所示樣本進行測試。
awk -v RS='"[^\n]*|\n+' '
RT=="\n"{ next }
$0~/^msgstr/{
if(RT=="\"\""){ $0=$0 val }
else { $0=$0 RT }
}
$0~/^msgid/ { val=RT
$0=$0 RT }
RT
' Input_file
說明:為上述添加詳細說明。
awk -v RS='"[^"]*"|\n+' ' ##Starting awk program from here and setting record separator as " till " comes or new lines.
RT=="\n"{ next } ##If RT is newline then take cursor to next line.
$0~/^msgstr/{ ##Checking if line starts from msgstr then:
if(RT=="\"\""){ $0=$0 val } ##Checking if RT us "" then add val to current line.
else { $0=$0 RT } ##Else simply add RT.
}
$0~/^msgid/ { val=RT ##Checking if line starts from msgid then make val to RT
$0=$0 RT } ##Adding RT to $0.
RT ##Printing line if RT is not null.
' Input_file ##Mentioning Input_file name here.
這可能對您有用(GNU sed):
sed -E 'N;s/(msgid "(.*)".*msgstr )""/\1"\2"/;P;D' file
打開兩行 window ,如果第一行包含msgid
和第二個msgstr ""
,則將msgstr
值替換為msgid
值。 打印/刪除第一行並重復。
由於輸入文件的結構如此簡單和一致,我認為以下內容應該足夠了(它適用於您提供的 3 個示例):
sed -zE 's/(msgid "([^"]+)"\nmsgstr ")"/\1\2"/g' your_file
-z
使文件成為嵌入\n
的長字符串,因此我們不需要像N
, D
或其他命令,因為整個文件已經在模式空間中;-E
讓我們使用(
, )
和+
代替\(
, \)
和\+
(以及其他類似的東西)()
捕獲msgid "Hello"\nmsgstr "
(關閉的"
匹配但未捕獲);()
捕獲第一個雙引號字符串;\1\2"
連接匹配的文本(除了最后的"
,正如我上面提到的),前兩個"
之間的文本和結束"
,g
將在整個文件中應用替換。 如果前導字符串不是那么重要(例如,它們始終相同,並且行始終顯示為msgid
后跟msgstr
),您可以再壓縮上面的命令:
sed -zE 's/(([^"]+)"\n[^\n]*")"/\1\2"/g' your_file
您可以使用保持空間:
sed '
/^msgid[\t ]*/ {
p
s///
x
d
}
/^msgstr[\t ]*""/ {
x
s/^/msgstr /
}
' <in.po >out.po
msgid
開頭
msgstr
開頭並且具有空值
這是一個簡單的sed
腳本,它將最新的msgid
保存在保持空間 ( h
) 中,然后將其帶回 ( x
) 並在看到空msgstr
msgstr
sed -e '/^msgid "/h' -e '/^msgstr ""/!b' \
-e x -e 's/^msgid/msgstr/' it.po >it2.po
另請注意,您通常如何將多個sed
語句與-e
組合在一起,而不是創建一個新文件,然后在其上重復運行sed -i
。 sed
是一種腳本語言; 如果您想使用它,請學習它。
(一些sed
變體不能容忍這種安排;如果您遇到問題,可以將腳本組合成一個字符串,在語句之間使用分號。)
話雖如此, sed
在很大程度上是一種只寫語言。 也許您最好使用簡單的 Awk(或 Python 等)解決方案。
awk '/^msgid "/ { s=$0; sub(/^msgid/, "", s) }
/^msgstr ""/ { $0 = $1 s } 1' it.po >it2.po
保持簡單並使用 awk,例如在每個 Z6EC1B201EA6A5D727BDDD 框上的任何 shell 中使用任何 awk:F
$ awk '$2~/""/{$2=p} {p=$2} 1' it.po
msgid "Hello"
msgstr "Hello"
msgid "Dog"
msgstr "Cane"
如果這不是您所需要的,那么編輯您的問題以提供更全面的示例輸入/輸出,包括不適用的案例。
Since you have GNU sed for -i
you also have or can install GNU awk for -i inplace
inplace if you want "inplace" editing, or just do tmp=$(mktemp) && awk 'script' file > "$tmp" && mv "$tmp" file
,就像你對任何其他命令一樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.