awkでリストファイルを使用してデフォルトファイルを編集する

awkでリストファイルを使用してデフォルトファイルを編集する

みんな。 ports.lstとmaster.tblという2つのファイルがあります。

ports.lstは次のようになります。

hawaii-P1
hawaii-P2
hawaii-P3
losangeles-P1
losangeles-P3

master.tblは次のようになります。

#Site 1 Honolulu
servername HAWAII-A hawaii-P1 InitFileA OutFileA otherfields
servername HAWAII-A hawaii-P2 InitFileA OutFileA otherfields
#servername HAWAII-A hawaii-P3 InitFileA OutFileA otherfields
servername HAWAII-A hawaii-P4 InitFileA OutFileA otherfields

#Site 16 Dallas
servername DALLAS-A dallas-P1 InitFileA OutFileA otherfields
servername DALLAS-A dallas-P2 InitFileA OutFileA otherfields
servername DALLAS-A dallas-P3 InitFileA OutFileA otherfields

#Site 8 L.A.
#servername LOSANGELES-A losangeles-P1 InitFileA OutFileA otherfields
servername LOSANGELES-A losangeles-P2 InitFileA OutFileA otherfields
#servername LOSANGELES-A losangeles-P3 InitFileA OutFileA otherfields

ports.lstにリストされているすべてのポートに対してmaster.tblファイルを検索し、ファイルが次のように「InitFileA」と「OutFileA」を置き換える必要があります。

#Site 1 Honolulu
servername HAWAII-A hawaii-P1 InitFileB-hawaii-username-ALPHA-password OutFileB-hawaii-username-ALPHA otherfields
servername HAWAII-A hawaii-P2 InitFileB-hawaii-username-ALPHA-password OutFileB-hawaii-username-ALPHA otherfields
#servername HAWAII-A hawaii-P3 InitFileB-hawaii-username-ALPHA-password OutFileB-hawaii-username-ALPHA otherfields
servername HAWAII-A hawaii-P4 InitFileA OutFileA otherfields

#Site 16 Dallas
servername DALLAS-A dallas-P1 InitFileA OutFileA otherfields
servername DALLAS-A dallas-P2 InitFileA OutFileA otherfields
servername DALLAS-A dallas-P3 InitFileA OutFileA otherfields

#Site 8 L.A.
#servername LOSANGELES-A losangeles-P1 InitFileB-losangeles-username-ALPHA-password OutFileB-losangeles-username-ALPHA otherfields
servername LOSANGELES-A losangeles-P2 InitFileA OutFileA otherfields
#servername LOSANGELES-A losangeles-P3 InitFileB-losangeles-username-ALPHA-password OutFileB-losangeles-username-ALPHA otherfields

それが私が今いるところですが、明らかに失敗しました。

awk 'NR==FNR{z[$0];next}{if ($3 in z && $4 == "InitFileA"){ c=(echo $3| awk -F '-' {print $1});$4="InitFileB-"c"-username-ALPHA-password";$5="OutFileB-"c"-username-ALPHA"}}1' ports.lst master.tbl > output.tbl

私も次のことを試しました。

awk 'NR==FNR{z[$0];next}{if ($3 in z && $4 == "InitFileA"){ c=$3; sub(/-.*/, "", $c);$4="InitFileB-"c"-username-ALPHA-password";$5="OutFileB-"c"-username-ALPHA"}}1' ports.lst master.tbl > output.tbl

私はこれについて心配してきました。ここで誰が私が間違っているかについての洞察を提供できますか?

ベストアンサー1

タスクを2つのラウンドに分割する正しい基本的なアイデアがありますが、awkルールでawkを呼び出します。ここでは読み取りを中止しました。このように単純な問題に対する解決策は複雑すぎる。

次のawkの部分を考えてみましょう。

awk 'BEGIN {
         RS = "[\t\v\f ]*(\r\n|\n\r|\r|\n)";
         FS = "[\t\v\f ]+"
     }

     FNR==1 {
         file++
     }

     /^#/ {
         next
     }

     file==1 {
         port[$1] = $1
     }

     file>=2 && ($3 in port) {
         base = $3;
         sub(/-[^-]*$/, "", base);
         $4 = "InitFileB-" base "-username-ALPHA-password";
         $5 = "OutFileB-" base "-username-ALPHA";
     }

     file>=2 {
         printf "%s\n", $0
     } ' ports.lst master.tbl

注:上記のすべてを1行に書き込むために必要なセミコロンを追加しました。

サンプル入力ファイルを使用して上記のコードを実行すると、次のような結果が得られます。

losangeles-P1
losangeles-P3
servername HAWAII-A hawaii-P1 InitFileB-hawaii-username-ALPHA-password OutFileB-hawaii-username-ALPHA otherfields
servername HAWAII-A hawaii-P2 InitFileB-hawaii-username-ALPHA-password OutFileB-hawaii-username-ALPHA otherfields
servername HAWAII-A hawaii-P4 InitFileA OutFileA otherfields

servername DALLAS-A dallas-P1 InitFileA OutFileA otherfields
servername DALLAS-A dallas-P2 InitFileA OutFileA otherfields
servername DALLAS-A dallas-P3 InitFileA OutFileA otherfields

servername LOSANGELES-A losangeles-P2 InitFileA OutFileA otherfields

このBEGIN規則は、ファイルが異なる改行エンコードを使用する他のシステム(Windowsなど)から送信されている場合にのみ、汎用改行サポートを設定します。

このFNR==1ルールは、file処理中のファイルを反映するように変数を更新します(1番目は1、2番目は2)。

この/^#/ { next }ルールは、ハッシュタグで始まるすべての行をスキップします。これはコメントであるため、保存する必要はありません。/^[\t\v\f ]*$/ { next }出力ファイルを圧縮したい場合は、空白行をすべてスキップするルールを追加することもできます。

このfile == 1 { port[$1] = $1 }ルールは、最初のファイルのすべての最初のフィールドを連想配列に追加しますport。割り当てられた値(= $1)は重要ではないので、= 0ここで実際に使用できます。

ルールfile >= 2 && ($3 in port)は2番目とそれ以降のファイルに適用され、3番目のフィールドが連想配列のキーの1つと一致する場合に実行されますport。 (値は重要ではなくキーのみを確認します。)つまり、この規則は、3番目のフィールドがポートリストで指定されたキーの1つである場合にのみ適用されます。

3番目のフィールドは変数にコピーされますbase。これはのキーの1つと一致し、port[]最後のフィールド以降のすべてのエントリは-を使用して削除されますsub()。次に、4番目と5番目のフィールドを変更します。 awk には文字列連結演算子はありません。ただ文字列を合わせるだけです。つまり、「foo」、文字列に変換された変数値、「bar」("foo" a "bar")で構成される文字列です。a

最後のルールは(変更可能な)レコードを印刷しますが、改行\n文字を使用する必要があります。 2番目以降のファイルのレコードのみが使用されます。

ports.lst各ユーザー名とパスワードを含めるように上記の内容(3行が変更されましたか?)を少し変更します。しかし、全体的なアプローチを見ることができることを願っています。

おすすめ記事