bash - 在脚本中使用 sed 将文件内容替换为行

标签 bash macos text sed replace

我想使用 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"

Tested on repl .

关于bash - 在脚本中使用 sed 将文件内容替换为行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62831744/

相关文章:

linux - 在自动启动中以 root 身份执行脚本

bash - 如何绑定(bind)向上箭头键以转到下一个唯一命令(macOS 终端)?

macos - 在 Mac 上的 XAMPP 上设置虚拟主机

objective-c - 最小 cocoa 应用程序 - 菜单问题

r - 从 R 中的文本中提取文本引用(字符串)

opencv - 使用 OCR 阅读循环文本

linux - 将程序的输出日志传递给函数,同时将返回码存储在变量中

linux - 比较 boolean 变量以检查互联网连接

swift - 如何在 didSet 之后将数据从 AppDelegate 传递到 ViewController?

google-chrome - SVG 被切断