簡體   English   中英

sed 在下一行復制 substring

[英]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

這個腳本有兩個問題(至少):

  1. 當 msgstr 不為空時,也將 msgid 復制到 msgstr;
  2. 我很確定存在單行或更優雅的解決方案。

任何幫助,將不勝感激。 提前致謝。

您可以考慮使用更好的工具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的長字符串,因此我們不需要像ND或其他命令,因為整個文件已經在模式空間中;
  • -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開頭
    • 打印它
    • 刪除關鍵字
    • 保存字符串以保持
    • go 到下一行
  • 否則,如果行以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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM