我的脚本中有一个我想更改的变量:
read -p "Enter the name of city: " city
if [[ $city =~ Liverpool ]]; then
sed -i -e "/\$type\_of\_city =/ s/= .*/= ${city}/" /cities
echo -e "Liverpool: `grep '$name_of_city' cities"
fi
在城市文件中有一个#
我想删除的变量:
#$type_of_city = something
所以我想同时更改something
为Liverpool
实际上适用于上面的代码,但我不知道如何删除该#
标志。
现在我明白了#$type_of_city = Liverpool
,但我想看看$type_of_city = Liverpool
。
答案1
稍微修正一下代码块,
read -p "Enter the name of city: " city
if [ "$city" = 'Liverpool' ]
then
sed -Ei 's/^#* *(\$type_of_city) *= *.*/\1 = '"$city"'/' cities
printf "%s: %s\n" "$city" "$(grep -F "$city" cities)"
fi
在这里,我们将该行与扩展 RE 相匹配^#* *(\$type_of_city) *= *.*
。分解它代表:
^
- 行的开头#*
- 零个或多个#
字符*
- 零个或多个空格(
…)
- 封闭块上的匹配,稍后用作\1
\$type_of_city
- 文字字符串$type_of_city
(\$
经过转义以防止与行尾错误匹配)*
- 零个或多个空格=
- 文字字符*
- 零个或多个空格.*
- 零个或多个任意字符
如果匹配成功,我们将该行重写为\1 = $city
,其中\1
是括号中的(
… )
ERE 匹配的值,$city
是变量的值。
请注意,我们将变量的值$city
直接放入sed
替换字符串中,因此如果它包含诸如 的字符/
或诸如 的序列,\1
它将产生(最多)意外的结果,甚至导致sed
失败。在当前代码中,这是通过if
要求输入值为 的子句进行保护的Liverpool
,但如果您要删除该子句或过于放松它,则可能会遇到此问题。
答案2
在您的情况下,我会将整行替换为sed
,其中#
被锚定为行开头之后的可选字符:
sed "s/^#\{0,1\}\$type_of_city =.*/type_of_city = $city/" /cities
这将取代
#
紧随该行开头 ( ) 之后出现 0 或 1 次^
,后跟- 文字字符串
$type_of_city =
,后跟 - 任意文本直到行尾
与$type_of_city =
,后跟内容壳多变的$city
。
您使用的地址说明符不是必需的,因为只有在搜索模式匹配时才会执行替换。
笔记由于您$city
从用户输入中获取,因此您应该确保在使用之前验证/清理输入;否则你将打开你的脚本代码注入漏洞如果用户sed
在输入中包含命令语法。
正如 Stéphane Chazelas 在评论中指出的那样,您可以通过使用perl
而不是通过环境或作为参数sed
传递值的位置来避免这种情况,而不是将其嵌入到代码中。$city
sed