我想使用 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
但是文件没有改变。
我认为没有发生任何事情,因为我想更改的行有一些特定的字符( <
、 /
、..),但脚本在“正常”行上也不起作用。
我还认为问题是因为文件是使用描述 rune 件以读取模式打开的,但我可以使用 sed 更改文件的内容,例如使用以下命令:
sed -i '' -e "9s/.*/TEST TEST/" $originalFile
我尝试了几种语法都没有成功,你可以找到我尝试过的脚本和不同的语法here .
有谁知道我做错了什么吗?
Stackoverflow 上有几个问题可以解决某种此类问题,但没有一个有帮助。
如果我的第一个意图是用 sed 替换这些行,任何其他解决方案将不胜感激。
最佳答案
您的脚本有一些错误:
- 正则表达式是错误的,它与输入不匹配。
-
sed
适用于正则表达式,而不适用于确切的字符。所以/$line/
会被解析为正则表达式。 - 变量不展开单引号。
'/$line/'
匹配 literally 5 个字符$line
.要扩展变量,请使用双引号。 stackoverflow difference between single and double quotes in bash . - 在执行
sed
时循环每一行是没有意义的.sed
已经在每一行执行... -
function func() {
在 bash 上支持作为支持奇怪语法的扩展,不应该使用它。就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"
关于bash - 在脚本中使用 sed 将文件内容替换为行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62831744/