【问题标题】:SED find string using variable, edit, and then substitutionSED 使用变量查找字符串,编辑,然后替换
【发布时间】:2014-10-28 14:59:41
【问题描述】:

我在尝试使用包含正斜杠的变量使用 SED 编辑文件时遇到一些问题。

我正在尝试编辑“校验和”的文件具有以下内容...

758f9775093bf885dbc963cba1aec732,/bin/bash
1b45027142521f2a1c3d95891770eb47,/etc/grub.conf
2a34dc288f7994cc7b1b338605ef8775,/etc/hosts
03f670845fe199955f9a0babecbda9a0,/etc/networks

我想使用变量(file_path=“/bin/bash”)搜索字符串“/bin/bash”,当我找到该字符串时,删除“,”之前的所有内容并替换为“有效的”。

下面是我的 sed 语法和尝试,但是当我尝试使用该变量时它失败了。有什么建议吗?

没有变量的成功

# sed '\/bin\/bash/ s/^.*,/VALID,/g' checksum
VALID,/bin/bash
1b45027142521f2a1c3d95891770eb47,/etc/grub.conf
2a34dc288f7994cc7b1b338605ef8775,/etc/hosts
03f670845fe199955f9a0babecbda9a0,/etc/networks

变量失败

# file_path="/bin/bash"
# echo $file_path
/bin/bash

# sed '/$file_path/ s/^.*,/VALID,/g' checksum
758f9775093bf885dbc963cba1aec732,/bin/bash
1b45027142521f2a1c3d95891770eb47,/etc/grub.conf
2a34dc288f7994cc7b1b338605ef8775,/etc/hosts
03f670845fe199955f9a0babecbda9a0,/etc/networks

我尝试将变量用引号 {} 括起来,但仍然失败:

# sed '/"$file_path"/ s/^.*,/VALID,/g' checksum
758f9775093bf885dbc963cba1aec732,/bin/bash
1b45027142521f2a1c3d95891770eb47,/etc/grub.conf
2a34dc288f7994cc7b1b338605ef8775,/etc/hosts
03f670845fe199955f9a0babecbda9a0,/etc/networks

# sed '/{$file_path}/ s/^.*,/VALID,/g' checksum
758f9775093bf885dbc963cba1aec732,/bin/bash
1b45027142521f2a1c3d95891770eb47,/etc/grub.conf
2a34dc288f7994cc7b1b338605ef8775,/etc/hosts
03f670845fe199955f9a0babecbda9a0,/etc/networks

我也用过“|”作为转义字符。

# sed '|{$file_path}| s|^.*,|VALID,|g' checksum
sed: -e expression #1, char 1: unknown command: `|'

关于如何完成此任务的任何建议?

# sed --version
GNU sed version 4.2.1

【问题讨论】:

    标签: sed


    【解决方案1】:

    单引号禁止变量替换。试试这个:

    sed "\:$file_path: s/^.*,/VALID,/" checksum
    

    请注意,我已将模式分隔符更改为冒号,以便变量值中的斜线不会结束模式。

    【讨论】:

    • 完美!我会用这个。在使用不同的分隔符进行测试时,我发现另一个地方我错了。我没有逃避他们。感谢您的帮助。
    【解决方案2】:

    完成@ooga 的好答案。保留单引号可能会很有趣,以避免 bash 可以解释的特殊字符可能出现的歧义。为此,您可以简单地用单引号关闭 sed 块,以便稍后重新打开它:

    sed '\~'$file_path'~s~^[^,]*~VALID~' checksum
    

    【讨论】:

    • 使用 oogas 的答案 $file_path 在双引号内,但对于您的答案,则不在任何引号内。怎么样更好?
    • 没有好坏之分,这是用单引号做的方式。主要的兴趣是你可以在单引号之间写任何你想要的东西,而不用 bash 解释它。
    • @CasimiretHippolyte 我在这里请求不同。不以避免 bash 来解释不存在的插值元素为代价引用变量实际上更糟。 :P
    • @CasimiretHippolyte 您的变量不在单引号之间,而是在任何引号之外。如果您希望脚本的 REST 使用单引号而不是双引号,那么您可以将其写为 sed '\~'"$file_path"'~s~^[^,]*~VALID~' checksum,但我没有看到增加此脚本复杂性的好处。
    • +1 @CasimiretHippolyte,我必须将我的 sed 命令放在 bash 脚本中,并使用您的语法正确解释变量。我很高兴你提出你对这个问题的看法。
    【解决方案3】:

    只需使用 awk 来过简单的生活:

    awk -v fp="$file_path" 'BEGIN{FS=OFS=","} $2==fp{$1="Valid"} 1' file
    

    无论file_path 的内容是什么,包括/ 或RE 元字符或shell 通配符,这都会起作用,并且如果它的内容与文件中行的任何部分部分匹配,则不会产生错误匹配。

    【讨论】:

    • 谢谢你这确实有效,我总是让我的生活更轻松。我应该开始使用更多的 awk,但倾向于使用 sed,因为我知道的更多。
    猜你喜欢
    • 1970-01-01
    • 2021-09-28
    • 2011-10-13
    • 2013-03-23
    • 2022-11-15
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    相关资源
    最近更新 更多