用脚本中的 sed 将行替换为文件的内容
Posted
技术标签:
【中文标题】用脚本中的 sed 将行替换为文件的内容【英文标题】:Replace lines with the content of a file with sed in a script 【发布时间】:2020-10-31 01:05:02 【问题描述】:我想使用 sed(在 MacOs 上)将文件中的某些行替换为另一个文件的内容。
假设文件如下,我想替换所有包含<iframe src=...0></iframe>
的行。
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Paupertas si malum est, mendicus beatus esse nemo
<iframe src="https://test.com/bar/11d75d1c627c017299e4fe35e" frameborder=0></iframe>
oportunitatis esse beate vivere. Quasi vero, inquit, perpetua oratio rhetorum solum, non etiam philosophorum
<iframe src="https://test.com/bar/9e4e1b69131bf5d718452aca6" frameborder=0></iframe>
vivere. Quasi vero, inquit, perpetua oratio rhetorum solum, non etiam philosophorum
在命令行上,以下命令运行良好:
$ sed -i '' -e "/$line/r $replacementFile" -e "//d" $originalFile
在哪里
$line
是要更改的行
line="\<iframe src=\"https:\/\/test\.com\/bar\/11d75d1c627c017299e4fe35e\" frameborder=0\>\<\/iframe\>"
$replacementFile
指向内容必须替换$line
s的文件,其内容如下:
LOREM IPSUM DOLOR
AMET, CONSECTETUR
ADIPISCING ELIT.
$originalFile
是必须更改 $line
的文件的路径
我有几个文件要修改,每个文件都包含几行要更改。所以我写了一个脚本,其中<iframe src=...0></iframe>
类型的所有行都用正则表达式找到,然后我应用在命令行上工作的命令。
以下是我写的原始脚本:
function replaceTextWithFile()
# File to modify (in production the name is passed as an argument)
local originalFile="./file.txt"
# Regex to find the line to change
local regex="<iframe src=\"(https:\/\/test.*)\" frameborder"
# Regex on "normal" line does not work neither
#local patternToReplace="^oportu.*"
# The file whose content must replace the line
local replacementFile="./new_content"
exec 4<"$originalFile"
while read line <&4 ; do
if [[ $line =~ $regex ]];then
echo "PATTERN FOUND"
sed -i '' -e '/$line/r $replacementFile' -e '//d' $originalFile
fi
# Following command changes the 9th line successfully
sed -i '' -e "12s/.*/TEST TEST/" $originalFile
done
exec 4<&-
replaceTextWithFile
但文件没有改变。
我认为没有发生任何事情,因为我要更改的行有一些特殊字符(<
、/
、..),但脚本在“正常”行上也不起作用。
我还认为问题是因为文件是用描述符文件以读取模式打开的,但是我可以使用 sed 更改文件的内容,例如使用以下命令:
sed -i '' -e "9s/.*/TEST TEST/" $originalFile
我尝试了几种语法都没有成功,你可以找到我尝试过的脚本和不同的语法here。
有人知道我做错了什么吗?
*** 上有几个问题可以解决某种问题,但都没有帮助。
如果我的第一个意图是用 sed 替换这些行,任何其他解决方案都将不胜感激。
【问题讨论】:
''
在sed -i '' ...
中的作用是什么?
哇,$line =~ $regex
和 /$line/
的意义何在?不,sed
使用正则表达式,而不是精确行。还有为什么要反向引用(https....)
?你打算匹配(
)
吗?为什么https:\/\/foo
- 输入中没有foo
。 @LxerLx 指定备份后缀
@KamilCuk,我的意图是如果该行与正则表达式($line =~ $regex
)匹配,则更改所有行。 sed 不适用于确切的行?好的,我会朝这个方向搜索,谢谢
$line =~ $regex), then change the all line.
毫无意义。 sed
已经适用于文件中的所有行。就像您在每一行上循环行号一样。
【参考方案1】:
您的脚本有一些错误:
正则表达式是错误的,它与输入不匹配。sed
适用于正则表达式,而不适用于确切的字符。所以/$line/
会被解析为正则表达式。
变量不扩展单引号。 '/$line/'
匹配 字面意思 5 个字符 $line
。要扩展变量,请使用双引号。 *** difference between single and double quotes in bash。
在执行sed
时循环每一行是没有意义的。 sed
已经在每一行执行...
bash 支持function func()
作为支持奇怪语法的扩展,不应该使用它。只需 func()
来定义一个函数。 bash-hackers wiki deprecated and obsolete syntax。
Following command changes the 9th line successfully
后跟一行更改第 12 行。
because the lines that I want to change have some particular characters
<
和 >
在正则表达式中没有特殊含义,但是 \<
\>
是 GNU sed extension。通过regex crosswords 学习正则表达式。
要读取一行输入,请使用IFS= read -r line
。 bashfaq how to read a file line by line。
只是:
replaceTextWithFile()
local originalFile="./file.txt"
local regex="<iframe src=\"https:\/\/.*\" frameborder"
local replacementFile="./new_content"
# note -i '' on macos I think
sed -i -e "/$regex/r $replacementFile" -e '//d' "$originalFile"
请注意,正则表达式可以更简单地写在单引号内,这样"
就不需要转义:
local regex='<iframe src="https:\/\/.*" frameborder'
或者您甚至可以在 sed
中使用不同的正则表达式分隔符来使其变得简单:
local regex='<iframe src="https://.*" frameborder'
sed "\~$regex~r $replacementFile"
Tested on repl.
【讨论】:
我在写我的问题时在我的正则表达式中犯了一个错误。但是,您的回答@KamilCuk 是正确的,可以解决我的问题。我也非常感谢所有有趣的建议!谢谢!!以上是关于用脚本中的 sed 将行替换为文件的内容的主要内容,如果未能解决你的问题,请参考以下文章