我有一个脚本,用于通过文件旋转并用文件中的随机行替换占位符{{su}},占位符在文件中多次出现,我需要它是一个每次随机。目前,它用相同的行替换每个占位符。
#!/bin/bash
subject=$(shuf -n1 *.subjects)
cat tmp.$file | sed -e "s/{{su}}/$subject/" > output.file
答案 0 :(得分:2)
接受的答案有微妙的缺陷:
{{su}}
在同一行上多次出现,则会为该行的每个模式{{su}}
执行相同的替换read
未与IFS=
和-r
开关一起使用,您会得到其他令人讨厌的惊喜:空间不一定会被保留,您将获得反斜杠解释(但这很容易修复),sed
将会混淆。一种有效的方法,但它涉及在内存中读取整个文件(它仅适用于少量{{su}}
的小文件):
#!/bin/bash
file=$(< filename.txt )
while [[ $file = *'{{su}}'* ]]; do
repl=$(shuf -n1 file.subjects)
file=${file/'{{su}}'/"$repl"}
done
printf '%s\n' "$file"
对于类似于接受的答案的方法,即逐行阅读:
#!/bin/bash
while IFS= read -r line; do
while [[ $line = *'{{su}}'* ]]; do
repl=$(shuf -n1 file.subjects)
line=${line/'{{su}}'/"$repl"}
done
printf '%s\n' "$line"
done < filename.txt
现在关于选择随机行的方法:虽然shuf
很好,但是它是一个外部进程,因为它将被多次调用(在子shell中),你可以考虑在Bash中实现类似的东西。如果您的行数量有限,您可以考虑将所有行拖入数组并从该数组中随机选择一个条目:
#!/bin/bash
mapfile -t replacements < file.subjects
nb_repl=${#replacements[@]}
while IFS= read -r line; do
while [[ $line = *'{{su}}'* ]]; do
repl=${replacements[RANDOM%nb_repl]}
line=${line/'{{su}}'/"$repl"}
done
printf '%s\n' "$line"
done < filename.txt
这仅适用于file.subjects
中的“小”行数(小,理解小于32767),并且如果您不太担心模数获得的分布。但是,有一些非常简单的解决方法可以解决这个问题。
注意。您正在使用shuf -n1 *.subjects
。使用多个文件调用shuf
是错误的(至少使用我的shuf
版本)。因此,如果glob *.subjects
扩展为多个文件,则会出错。
注意。如果您不想遇到无限循环,请确保替换不包含{{su}}
模式!
答案 1 :(得分:1)
你需要一个循环。首先使用wc -l
计算tmp.$file
中的行数。
然后循环计数次数,每次执行你拥有的两行shell脚本。
因此,在每个循环中,您将获得一个新主题并执行新的sed
。诀窍是使用sed
命令的地址,地址格式一次执行对一行的替换,传入地址的循环计数器。
类似于(伪代码):
$count = $(wc -l tmp.$file)
$i=1
cp tmp.$file > output.file
while $i < $count
subject = $(shuf -n1 *.subjects)
cat output.file | sed -e "$i,$is/{{su}}/$subject/" > output.file
$i=$i+1
end while
答案 2 :(得分:1)
在这种情况下,您需要在文件中逐行迭代,并在每次迭代时生成随机字符串。它将检查{{su}}
模式的所有行,如果发现它将用来自另一个文件的随机字符串替换它:
while read line
do
subject=$(shuf -n1 *.subjects)
sed -e "s/{{su}}/$subject/g" <<< "$line")
done <1.txt