我有一个脚本,它存储了$variable
行数不确定的文本。假设我已命名它script.bash
并且它位于$HOME
:
#!/bin/bash
# commands on the beginning of my script
variable='Lorem Ipsum is simply dummied
text of the printing and
typesetting industry. Lorem Ipsum has been the
industry standard dummy text ever since the 1500s'
# commands at the end of my script
我想创建一个新脚本来更改variable
on中的文本script.bash
。代码的想法是这样的:
#!/bin/bash
file="$HOME/script.bash"
mynewvariable='one
two
three'
substitute_everything_inside_variable () {
# code
}
substitute_everything_inside_variable "$mynewvariable" "$file"
只要它只是一行,就可以使用新行替换整行,sed
如下所示:
sed -i "5s/.*/$mynewvariable/" "$HOME/script.bash"
但考虑到我需要替换单引号内的所有内容(并且其中文本的行数是可变的),我不知道如何使用命令行工具来做到这一点。有没有一种方法可以在不阅读和解释每一行中发生的情况的情况下做到这一点?
答案1
替换文件的全部内容比更改包含许多您不想破坏的其他内容的文件中的多行引号字符串要容易得多。
尝试将 的内容放入$variable
文件中(例如vfile.txt
),并让您的 shell 脚本执行类似 的操作variable="$(cat vfile.txt)"
。
然后您可以使用任何您想要替换或修改的方法vfile.txt
。
答案2
Sed 还有除s
.您可以查找起始行,删除直到值的最后部分的所有行,然后插入新值。不过,要正确引用是很困难的 - 请注意,s/…/$mynewvariable/
不仅换行符会失败,而且'
,\
和也会失败/
。用 Perl 做起来更容易。
如果文件不是太大而无法放入内存,请告诉 Perl 读取整个文件,而不是将其逐行分解。未经测试。
mynewvariable=$mynewvariable perl -0777 -i -p -e '
$replacement = $ENV{mynewvariable};
$replacement =~ s/\x27/\x27\\\x27\x27/g;
s/^variable=\x27(?:[^\x27]|\x27\\\x27\x27)*\x27/$replacement/;
' "HOME/script.bash"
说明:
perl -0777 -i -p
对文件的内容运行 Perl 程序,然后替换该文件。-0777
意味着一次性处理整个文件,而不是逐行处理。sed s/…/$mynewvariable/
我通过环境传递变量,因为将它拼接到 Perl 程序中会导致它被解释为 Perl 代码而不是字符串(这与不起作用的原因相同)。\x27
是一个单引号(我将 Perl 代码放在单引号内,所以我不能在里面使用单引号)。$replacement =~ …
替换代表单引号 shell 字符串文字内部的'
值。'\''
'
(?:[^\x27]|\x27\\\x27\x27)
匹配'\''
任何不是 的字符'
。
答案3
由于您知道 script.bash 文件中变量所在的行号,因此您可以执行以下操作:
#!/bin/bash
file="$HOME/script.bash"
mynewvariable='one
two
three'
substitute_everything_inside_variable () {
tmpf=$(mktemp)
printf '%s\n' "$1" |
sed -e "s/'/'\\\''/g" -e 1s/^/variable=\'/ -e \$s/\$/\'/ > "$tmpf"
sed -i -e "4r $tmpf" -e '5s/^/#/' "$2"
rm -f "$tmpf"
}
substitute_everything_inside_variable "$mynewvar" "$file"
#### eof #####
这样您就可以避免变幻莫测的引用和 $ 变量的未知行跨度。
华泰