在 for 循环中使用 sed 替换多行和单词

在 for 循环中使用 sed 替换多行和单词

我在 Linux 机器上有 2 个包含数据的文件(macuid),我想将它们转移到带有列表的“模板”中,用于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

结果组合了列表的 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/template毫无意义,因为cat给出了一个文件,因此它将忽略其标准输入并简单地打印出文件的内容,忽略$i.无论如何,for i in `cat file`; do...这是不好的做法,不要使用它!看Bash 陷阱 #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++ ))的每次迭代结束时它都会增加一 ( ) 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",

相关内容