簡體   English   中英

將sed單線轉換為awk

[英]Translating a sed one-liner into awk

我正在解析包含“鍵=值”對行的文件。 一個例子可能是這樣的:

Normal line
Another normal line
[PREFIX] 1=Something 5=SomethingElse 26=42
Normal line again

我想保留所有不包含鍵值對的行,而按如下方式轉換所有包含鍵值對的行:

Normal line
Another normal line
[PREFIX]
  AAA=Something
  EEE=SomethingElse
  ZZZ=42
Normal line again

假設我有一個有效的翻譯詞典。

我現在要做的是將輸入傳遞給sed,在這里我將空格轉換為與'^\\['匹配'^\\['行的換行符。

然后將輸出通過管道傳遞到以下awk腳本中:

BEGIN {
    dict[1] = "AAA"
    dict[5] = "EEE"
    dict[26] = "ZZZ"

    FS="="
}   
{
    if (match($0, "[0-9]+=.+")) {
        key = ""
        if ($1 in dict) {
            key = dict[$1]
        }
        printf("%7s = %s\n", key, $2)
    }   
    else {
        print
        next
    }   
}   

整個命令行將變為:

cat input | sed '/^\(\[.*\)/s/ /\n/g' | awk -f script.awk

我的問題是:有什么辦法可以在中間包含sed操作,從而擺脫該額外的步驟?

$ cat tst.awk
BEGIN {
    split("1 AAA 5 EEE 26 ZZZ",tmp)
    for (i=1; i in tmp; i+=2) {
        dict[tmp[i]] = tmp[i+1]
    }
    FS="[ =]"
    OFS="="
}
$1 == "[PREFIX]" {
    print $1
    for (i=2; i<NF; i+=2) {
        print "  " ($i in dict ? dict[$i] : $i), $(i+1)
    }
    next
}
{ print }

$ awk -f tst.awk file
Normal line
Another normal line
[PREFIX]
  AAA=Something
  EEE=SomethingElse
  ZZZ=42
Normal line again

實際上,我不能強迫awk兩次讀取文件。 一個用於sed命令,一個用於您的算法,因此我不得不修改您的算法。

BEGIN {
    dict[1] = "AAA"
    dict[5] = "EEE"
    dict[26] = "ZZZ"

#    FS="="
}   
$0 !~/[0-9]+=.+/ { print }
/[0-9]+=.+/ {
   nb = split($0,arr1);
   for (i=1; i<=nb; i++ in arr1)  {
      nbb = split(arr1[i], keyVal, "=");
      if ( (nbb==2) && (keyVal[1] in dict) ) {
         printf("%7s = %s\n", dict[keyVal[1]], keyVal[2])
      } 
      else
         print arr1[i];
   }
}   

當您需要進行大量轉換時,可以先將dict文件遷移到sed腳本文件中。 當您的dicht文件具有固定格式時,您可以即時對其進行轉換。

假設你的dict文件看起來像

1=AAA
5=EEE
26=ZZZ

您的輸入文件是

Normal line
Another normal line
[PREFIX] 1=Something 5=SomethingElse 26=42
Normal line again

你想做類似的事情

cat input | sed '/^\[/ s/ /\n/g' | sed 's/^1=/  AAA=/'
# Or eliminating the extra step with cat
sed '/^\[/ s/ /\n/g' input | sed 's/^1=/  AAA=/'

因此,下一步是將dict文件轉換為sed命令:

sed 's#\([^=]*\)=\(.*\)#s/^\1=/   \2=/#' dictfile

現在您可以將它們與

sed '/^\[/ s/ /\n/g' input | sed -f <(
   sed 's#\([^=]*\)=\(.*\)#s/^\1=/   \2=/#' dictfile
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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