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"이 포함되고, 두 번째 파일에는 두 번째 "uid"와 두 번째 "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

결과는 목록의 두 이름을 결합하여 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/template, cat파일이 제공되므로 표준 입력을 무시하고 단순히 파일의 내용을 인쇄하므로 무시됩니다 . $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",

관련 정보