假设我有十个 bash shell 脚本:script1.sh
, script2.sh
, ..., script10.sh
。最初,所有十个文件都是相同的。
现在,我想在每个脚本中进行两处更改:
在每个文件中,我想更改特定行(例如第 8 行)——也就是说,删除第 8 行上的所有内容并将其替换为“持续的”我指定的字符串,例如
"This is line 8."
这类似于这个问题,但他们想用 替换"AAA"
,"BBB"
而我想用 替换第 8 行(无论它是什么)"This is line 8."
。在每个文件中,我想更改另一个特定行(例如第 21 行)并将其替换为“多变的”我指定的字符串。例如,
script1.sh
我想将第 21 行更改为"XYZ"
;我script2.sh
想将第 21 行更改为"PQR"
;我script3.sh
想将第 21 行更改为"ABC"
.本质上,这只是对函数的多次调用(1)如上所述——除了我将在一个单独的文件而不是所有文件中进行更改,并且我指定十个不同的字符串而不仅仅是一个。所以要得到(2)在这里,也许我会打电话(1)十个不同的时间,不同的参数。
bash
我对使用常用 Linux 程序(如、vi
、awk
、gawk
等)的解决方案感兴趣。
答案1
for file in f1 f2; do
sed -i '8s/^.*$/foo/' "$file"
done
答案2
使用 awk
for file in script1.sh script2.sh script3.sh ... script10.sh; do
temp=$(mktemp)
awk '
BEGIN {
line8 = "This is line 8"
line21["script1.sh"] = "XYZ"
line21["script2.sh"] = "PQR"
line21["script3.sh"] = "ABC"
# ...
}
FNR == 8 { print line8; next }
FNR == 21 && FILENAME in line21 { print line21[FILENAME]; next }
{print}
' "$file" > "$temp" && mv "$temp" "$file"
done
或者,使用 bash 和 sed
# bash variables to store new values. requires bash v4 for the associative array
line8="This is line 8"
declare -A line21=(
[script1.sh]="XYZ"
[script2.sh]="PQR"
[script3.sh]="ABC"
# ...
)
# then use sed
for file in script1.sh script2.sh script3.sh ... script10.sh; do
sed -i "8s/.*/$line8/; 21s/.*/${line21[$file]}/" "$file"
done
使用 sed 解决方案,您必须小心新行不包含“/”字符,因为这会破坏命令s///
。尽管您可以使用不同的分隔符,例如s|pattern|replacement|
(在这种情况下,递归地应用相同的警告)
ed
也有效:
for file in script1.sh script2.sh script3.sh ... script10.sh; do
ed "$file" <<ED_COMMANDS
8d
8i
$line8
.
21d
21i
${line21[$file]}
.
w
q
ED_COMMANDS
done
答案3
我将回答这两个问题,但作为一般规则,请不要合并这样的问题,而是将它们分成单独的帖子。
问题1
珀尔:
for f in *.sh; do perl -i -lne '$.==8 ? print "This is line 8" : print;' "$f"; done
awk 及其变体:
for f in *.sh; do awk '{if(NR==8){print "This is line 8"}else{print}}' "$f" > fifo && mv fifo "$f"; done
问题2
我首先会创建一个文件,其中包含我想要进行的替换。例如:
script1.sh foo1
script2.sh foo2
script3.sh foo3
script4.sh foo4
然后读取该文件以执行替换:
while read f s; do
export s;
perl -i -lne '$.==8 ? print "$ENV{s}" : print;' "$f";
done < sublist.txt