Shell脚本 - 使用带有/的变量的sed

时间:2022-09-08 15:28:56

I am new to shell script and don't know much. I have a set of files on which I want to append some text. I am not sure of a better way to do it, but I am using sed to do so. I have written the following script in bash to do so(I am testing it out with one file out of the set of files in the following). Here, I am replacing </notepads> with </notepads> "\n" <text to be appended> in order to append <text to be appended> after the string </notepads> in the file UIL_extract.ktr. (</notepads> occurs only once in the file)

我是shell脚本的新手,不太了解。我有一组文件,我想在其中添加一些文本。我不确定一个更好的方法,但我使用sed这样做。我在bash中编写了以下脚本来执行此操作(我正在使用以下文件集中的一个文件对其进行测试)。在这里,我将 替换为 “\ n” <要附加的文本> ,以便在文件UIL_extract.ktr中的字符串 之后追加 <要附加的文本> 。 ( 在文件中只出现一次)

  FILE=UIL_extract.ktr
  FIND="</notepads>"
  SUB="$FIND"$'\n'`cat add.txt`
  echo "Finding $FIND in $FILE"
  echo "with $SUB"
  sed "s,${FIND},${SUB},g" $FILE > Temp.ktr

This is the error I get when I execute it -

这是我执行时遇到的错误 -

sed: -e expression #1, char 25: unterminated `s' command

Something is not right and I don't know what.

有些东西不对,我不知道是什么。

Thanks in advance.

提前致谢。

PS - I have tried various other things. Eg. if I do -

PS - 我尝试了其他各种各样的东西。例如。如果我做 -

sed 's,"${FIND}","${SUB}",g' $FILE > Temp.ktr

It probably doesn't expand the variables as it does not replace it on the output.

它可能不会扩展变量,因为它不会在输出中替换它。

4 个解决方案

#1


1  

You need to get the quoting right - so that bash can read the bash variables.

您需要正确引用 - 以便bash可以读取bash变量。

sed 's,'"${FIND}"','"${SUB}"',g' $FILE > Temp.ktr

The other problem is handling the '/n' in and possibly other characters. I would try something like:

另一个问题是处理'/ n'和可能的其他字符。我会尝试类似的东西:

awk '{print}  /<\/notepads>/ {exit}' $FILE > /tmp/f1
awk 'BEGIN{found=0} /<\/notepads>/ {found=1;next} {if (found)print}' $FILE >/tmp/f2
cat /tmp/f1 add.txt /tmp/f2 > Temp.ktr
rm /tmp/f[23]

#2


0  

Change your code to SUB="$FIND"$'\n'`cat add.txt` on line #4 and it will work.

在第4行将代码更改为SUB =“$ FIND”$'\ n'`cat add.txt`,它将起作用。

#3


0  

You want to add the contents of file add.txt after you find the text </notepads>? That's just:

您想在找到文本 后添加文件add.txt的内容?那只是:

awk 'NR==FNR{add = add $0 ORS; next} {print} /<\/notepads>/{printf "%s",add}' add.txt UIL_extract.ktr

sed actually has a r command specifically for this, but using sed for anything multi-line is not extensible and gets very complicated very fast so you should just learn awk.

sed实际上有一个专门用于此的r命令,但是使用sed进行任何多行都不是可扩展的并且非常快速地变得非常复杂,所以你应该学习awk。

#4


0  

To recap:

回顾一下:

The only problem in the original code is that in an s function's replacement text literal \n chars. must be \-escaped - otherwise the sed command will break.

原始代码中唯一的问题是在s函数的替换文本文字\ n字符中。必须是\ -escaped - 否则sed命令将会中断。

While you could use bash's variable expansion features to escape the newlines in $SUB - SUB=${SUB//$'\n'/\\$'\n'} - a much simpler solution is to use sed's r <file> function (as @Ed Morton states in his answer), which can be used to output a file's content whenever the preceding context address (regex) matches (after outputting the current line):

虽然您可以使用bash的变量扩展功能来转义$ SUB中的换行符 - SUB = $ {SUB // $''\ n'/ \\ $'\ n'} - 一个更简单的解决方案是使用sed的r 函数(如@Ed Morton在其答案中所述),只要前面的上下文地址(正则表达式)匹配(在输出当前行之后),它就可用于输出文件的内容:

FIND='</notepads>'
sed "\,${FIND}, r add.txt" "$FILE" > Temp.ktr

Note that in order to use , as the regex delimiter, the initial delimiter must be \-escaped.

请注意,为了使用,作为正则表达式分隔符,初始分隔符必须是\ -escaped。

#1


1  

You need to get the quoting right - so that bash can read the bash variables.

您需要正确引用 - 以便bash可以读取bash变量。

sed 's,'"${FIND}"','"${SUB}"',g' $FILE > Temp.ktr

The other problem is handling the '/n' in and possibly other characters. I would try something like:

另一个问题是处理'/ n'和可能的其他字符。我会尝试类似的东西:

awk '{print}  /<\/notepads>/ {exit}' $FILE > /tmp/f1
awk 'BEGIN{found=0} /<\/notepads>/ {found=1;next} {if (found)print}' $FILE >/tmp/f2
cat /tmp/f1 add.txt /tmp/f2 > Temp.ktr
rm /tmp/f[23]

#2


0  

Change your code to SUB="$FIND"$'\n'`cat add.txt` on line #4 and it will work.

在第4行将代码更改为SUB =“$ FIND”$'\ n'`cat add.txt`,它将起作用。

#3


0  

You want to add the contents of file add.txt after you find the text </notepads>? That's just:

您想在找到文本 后添加文件add.txt的内容?那只是:

awk 'NR==FNR{add = add $0 ORS; next} {print} /<\/notepads>/{printf "%s",add}' add.txt UIL_extract.ktr

sed actually has a r command specifically for this, but using sed for anything multi-line is not extensible and gets very complicated very fast so you should just learn awk.

sed实际上有一个专门用于此的r命令,但是使用sed进行任何多行都不是可扩展的并且非常快速地变得非常复杂,所以你应该学习awk。

#4


0  

To recap:

回顾一下:

The only problem in the original code is that in an s function's replacement text literal \n chars. must be \-escaped - otherwise the sed command will break.

原始代码中唯一的问题是在s函数的替换文本文字\ n字符中。必须是\ -escaped - 否则sed命令将会中断。

While you could use bash's variable expansion features to escape the newlines in $SUB - SUB=${SUB//$'\n'/\\$'\n'} - a much simpler solution is to use sed's r <file> function (as @Ed Morton states in his answer), which can be used to output a file's content whenever the preceding context address (regex) matches (after outputting the current line):

虽然您可以使用bash的变量扩展功能来转义$ SUB中的换行符 - SUB = $ {SUB // $''\ n'/ \\ $'\ n'} - 一个更简单的解决方案是使用sed的r 函数(如@Ed Morton在其答案中所述),只要前面的上下文地址(正则表达式)匹配(在输出当前行之后),它就可用于输出文件的内容:

FIND='</notepads>'
sed "\,${FIND}, r add.txt" "$FILE" > Temp.ktr

Note that in order to use , as the regex delimiter, the initial delimiter must be \-escaped.

请注意,为了使用,作为正则表达式分隔符,初始分隔符必须是\ -escaped。