sed / awkを使用して2つのパターン間の単語を変更する

sed / awkを使用して2つのパターン間の単語を変更する

一部のテキストを処理する必要があるシェルスクリプトを作成していますが、次のテキストが表示されます。

read build { file1 file2 file3 }
check build { file2 file3 file4 }
read build { file4 file5 file6 }

すべてのファイルの前にテキストを追加したいと思います。つまり、「読み込みビルド」行の括弧の間に含まれる単語を意味します。これを達成するための最良のアイデアは何だと思いますか?結果は次のようになります。

read build { MY_ADDED_WORDfile1 MY_ADDED_WORDfile2 MY_ADDED_WORDfile3 }
check build { file2 file3 file4 }
read build { MY_ADDED_WORDfile4 MY_ADDED_WORDfile5 MY_ADDED_WORDfile6 }

行をつかんで配列に解析し、この「ファイル」文字列を追加したい単語に関連付けたいと思います。しかし、これが「スマート」ソリューションだとは思わない。ご協力ありがとうございます。

入力ファイルは次のとおりです。

set build { file1 file2 file3 file4 }
check $build

read build -new -f $build
read build -new -f { fileA fileB fileC fileD }

set build {file5 file6 file7 }

read build -old -f $build
read build -old -f { fileX fileZ fileD }

check_that_building

出力は次のようになります。

set build { file1 file2 file3 file4 }
check $build

read build -new -f $build
read build -new -f { MY_ADDED_WORDfileA MY_ADDED_WORDfileB MY_ADDED_WORDfileC MY_ADDED_WORDfileD }

set build {file5 file6 file7 }

read build -old -f $build
read build -old -f { MY_ADDED_WORDfileX MY_ADDED_WORDfileZ MY_ADDED_WORDfileD }

check_that_building

左括弧の前には常にスペースがありますが、右括弧の前にはスペースがあるかもしれませんが、必ずしもそうではありません。考えられる状況:

read build -old -f { fileX fileZ fileD }
read build -old -f {fileX fileZ fileD }
read build -old -f { fileX fileZ fileD}
read build -old -f {fileX fileZ fileD}

ベストアンサー1

sed 入力にまったく表示されないことがわかっている文字が1つ以上あると仮定しない限り、これを行う方法をすぐに理解することはできません。私はそれが#入力(またはあなたが追加した単語)に決して現れないと仮定します。これはうまくいくようです:

sed '/read build/ {
        s/{/{ /
        : fruit
        s/\({.*\) \([^}# ][^ ]*\)/\1#MY_WORD\2/
        t fruit
        s/#/ /g
        s/{ /{/
}'

これを含む行では、read build その後にスペースが挿入されます{。次に、{ 単語の後ろと単語(ファイル名かもしれません)の直前のスペースを検索します。スペースを置き換えて#単語を挿入してから、もう一度戻って詳細を見つけます。 (fruit任意のループラベルです。)すべての文字が見つかったら、#すべての文字を空白に戻し、挿入した空白(裏面{)を削除します。

#入力に表示されない入力に関する情報に加えて、次の情報も想定されます。

  • }各行の空白ではなく、最後の文字ですread build
  • 空白は空白だけです。タブはありません。

存在するawk

awk '/read build/ {
        in_braces=0
        for (i = 1; i <= NF; i++) {
                if ($i == "{") in_braces=1
                else if (substr($i,1,1) == "{") {
                        $i = "{MYWORD" substr($i,2)
                        in_braces=1
                }
                else if ($i == "}") in_braces=0
                else if (in_braces) $i = "MY_WORD" $i
        }
      }
      { print }'

各行read buildに対して、その行のすべての単語(フィールド)を繰り返します。状態変数()を使用して、aとaの間にあるかどうかをin_braces追跡します。その場合は、追加した単語で始まるように各単語を変更します。これはわずかに異なる2つの状況に対処する必要があることに注意してください。{}

  • 一言はい {、すべての後続の単語修正を開始するフラグを設定し、
  • 一言次から始まった {、実際には型の複合なので修正してください。{fileXそれはい{、追加された単語とfileXファイル名。また、すべての後続の単語を修正するためのフラグを設定します。

これは、タブ文字を単語区切り文字として受け入れますが、スペースを単一のスペースに縮小するという欠点があります。たとえば、次のように入力します。

read build    {    file1    file2    file3    }

出力を生成します

read build { MY_WORDfile1 MY_WORDfile2 MY_WORDfile3 }

さらに、これは次のように仮定します。

  • theは{単語の先頭にあります(つまり、前にスペースが続きます)。
  • }各行の空白ではなく、最後の文字またはread build別の単語(たとえば、前後にスペースを含む)

たとえば、複数のセットの中かっこを許可します。

read build { file1 file2 file3 } text to be left alone { file4 file5 file6 }

おすすめ記事