我查看了其他类似的问题,但答案对我没有帮助。我是 bash 新手,我的脚本中可能有语法错误,但我不知道在哪里。我试图在每次运行此脚本时更新 example.conf 文件中的用户。每个用户都有一个 name.pub 文件。
VAR1=$( ls | grep ".pub" |sed "s/.pub//g")
VAR2="@demo_project_users = "
res=$VAR2$VAR1
sed "s/@demo_project_users = .*/$res/g" example.conf
这会产生Unterminated 's' command
错误。
编辑:我将这些文件放在一个文件夹中
aaaaaaaaaa.pub eboh.pub get_usernames.sh mmusterfrau.pub plom.pub rrein.pub update_users.sh
dboh.pub example.conf leni.pub mmustermann.pub rcall.pub tani.pub
我想将所有用户名(不带 .pub)放在一行中,中间有一个空格,如下所示
@demo_project_users = (... all names here)
答案1
您的grep
文件名可能匹配多个文件名,其中给出的值$res
包含换行符。sed
当使用包含文字换行符的替换字符串时,GNU会按照您所描述的方式进行抱怨。
不要用于grep
过滤 的输出ls
。如果您想获取当前目录中与模式匹配的所有名称*.pub
,请使用
filenames=( *.pub )
这将创建一个包含与给定模式匹配的所有名称的数组。
然后:
sed 's/\(@demo_project_users = \).*/\1'"${filenames[*]%.pub}"'/g' example.conf
扩展"${filenames[*]%.pub}"
将扩展为由数组中的每个文件名组成的单个字符串filenames
,以空格分隔(或任何第一个字符$IFS
碰巧是;默认情况下为空格),并.pub
从每个文件名中删除后缀字符串。
它是"${filenames[*]}"
扩展为空格分隔字符串的位,也是从每个文件名中%.pub
删除后缀的位。.pub
答案2
$res
命令的替换是由 shell 完成的。如果值中有斜杠,sed 无法知道它不是命令的结束标记s
。同样,sed 会将任何反斜杠或 & 符号解释$res
为特殊字符。
如果反斜杠和与号不可能出现,$res
并且您知道另一个字符也不可能出现,请使用该字符作为分隔符。例如:
sed "s~@demo_project_users = .*~$res~g" example.conf
或者,通过在特殊字符前添加反斜杠来引用它们。
quoted_res=$(printf %s "$res" | sed 's/[\\\/&]/\\&/g')
sed "s/@demo_project_users = .*/$quoted_res/g" example.conf