sedを使用してforループの複数行と単語を置き換える

sedを使用してforループの複数行と単語を置き換える

Linuxシステムにデータを含む2つのファイル(macおよび)があり、データを変数に置き換えるためのリストを含むuid「テンプレート」に転送しようとしています。sed

リスト.txt:

CP00
CP01

mac.txt:

FF-AA-BB-AA-DD-AA
00-AA-11-AA-11-EE

uid.txt:

e3442342a
e43342f0a

型:

#Template for Cobbler:
"uid": "change1",
"mac_address": "change2",

テンプレートを含む2つのファイルが必要です。最初のファイルには最初の「uid」と最初の「mac」が含まれ、2番目のファイルには2番目の「uid」と2番目の「mac」が含まれます。

私はこれを試していますが、動作しません。

change1=$(cat /tmp/cobbler/uid.txt); 
change2=$(cat /tmp/cobbler/mac.txt); 
for i in `cat /tmp/cobbler/list.txt`; do 
    echo $i | cat /tmp/cobbler/template | 
      sed -e "s/change1/$change1/g" -e "s/change2/$change2/g" >> /tmp/cobbler/$i; 
done

結果はリストの2つの名前を組み合わせて、CP00CP01最初の「uid」と最初の「mac」だけを入れます。

誰でも私を助けることができますか?ありがとうございます!

答え1

awkを使用してください。

$ cat tst.sh
#!/usr/bin/env bash

cd /tmp/cobbler &&
awk '
FILENAME == ARGV[1] { uids[FNR] = $1 }
FILENAME == ARGV[2] { macs[FNR] = $1 }
FILENAME == ARGV[3] { outs[FNR] = $1 }
FILENAME == ARGV[4] {
    for ( outNr in outs ) {
        if ( $1 == "\"uid\":" ) {
            $2 = "\"" uids[++uidNr] "\","
        }
        if ( $1 == "\"mac_address\":" ) {
            $2 = "\"" macs[++macNr] "\","
        }
        print > (outs[outNr] ".txt")
    }
}
' uid.txt mac.txt list.txt template

$ ./tst.sh

$ head /tmp/cobbler/CP*
==> /tmp/cobbler/CP00.txt <==
#Template for Cobbler:
"uid": "e3442342a",
"mac_address": "FF-AA-BB-AA-DD-AA",

==> /tmp/cobbler/CP01.txt <==
#Template for Cobbler:
"uid": "e43342f0a",
"mac_address": "00-AA-11-AA-11-EE",

答え2

いくつかの理由でこれはうまくいきません。まず、change1=$(cat /tmp/cobbler/uid.txt);内容全体を/tmp/cobbler/uid.txt変数に入れます。

$ echo "$change1"
e3442342a
e43342f0a

それはあなたが望むものではありません。次にecho $i | cat /tmp/cobbler/templatecatファイルが提供されるので、標準入力を無視し、単にファイルの内容を印刷するので無視されます。$iとにかくfor i in `cat file`; do...これは悪い習慣です。使用しないでください!バラよりバッシュトラップ #1

お客様の要件を正しく理解すると、希望する結果が得られます。

c=1 
while read change1; do 
    listName=$(awk -v lnum="$c" 'NR==lnum' list.txt)
    change2=$(awk -v lnum="$c" 'NR==lnum' mac.txt) 
    sed "s/change1/$change1/; s/change2/$change2/" template > "$listName".txt
    (( c++ ))
done < uid.txt 

説明する

  • c=1:これは私たちが見ている行を追跡する変数です。ループ(( c++ ))が繰り返されるたびに1()ずつ増加しますwhile
  • while read change1; do ... ; done < uid.txt:各行を繰り返し、uid.txt各行を$change1
  • listName=$(awk -v lnum="$c" 'NR==lnum' list.txt)awk印刷する$lnum最初の行ですlist.txt$c(カウンタの)値をawkawk変数に渡しますlnum。次に、awk現在の行番号()がNR()と等しい場合は、その行を印刷します。最後に、この行を 。lnumNR==lnum$listName
  • change2=$(awk -v lnum="$c" 'NR==lnum' mac.txt):上記と同じですが、今回は$chahge2その行をインポートして保存しますmac.txt
  • sed "s/change1/$change1/; s/change2/$change2/" template > "$listName".txtsed:でコマンドを実行しtemplate、必要な代替操作を実行し、出力を名前付きファイルに保存します$listName.txt

サンプルデータの結果は次のとおりです。


$ ls
CP00.txt  CP01.txt  list.txt  mac.txt  template  uid.txt

$ cat CP00.txt 
#Template for Cobbler:
"uid": "e3442342a",
"mac_address": "FF-AA-BB-AA-DD-AA",

$ cat CP01.txt 
#Template for Cobbler:
"uid": "e43342f0a",
"mac_address": "00-AA-11-AA-11-EE",

関連情報