【问题标题】:Replace newline and variable in text file替换文本文件中的换行符和变量
【发布时间】:2019-09-17 16:37:01
【问题描述】:

我有以下文件~/hello.txt

qwe asd qwe
bash "$HOME/byobu.sh"
bash "$HOME/byobu.sh"
# asd yxc asd

如何替换以换行符和变量开头的字符串,以便文件生成:

qwe asd qwe
# bash "$HOME/byobu.sh"
bash "$HOME/byobu.sh"
# asd yxc asd

即将第二个字符串的第一次出现替换为其注释版本。 尝试以下命令:

byobu_line='bash "$HOME\/byobu.sh"'
sed -i '0,/\n'"$byobu_line"'/ s/\n'"$byobu_line"'/\n# '"$byobu_line"'/' ~/hello.txt

保持文件不变。

没有sed 的解决方案也被接受。

注意:这里的换行符\n是需要自己匹配替换的,因为如果没有它再运行它会导致不想要的结果

qwe asd qwe
# # bash "$HOME/byobu.sh"
bash "$HOME/byobu.sh"
# asd yxc asd

【问题讨论】:

  • 这种事情在awk 中通常比sed 更容易。

标签: regex linux ubuntu awk sed


【解决方案1】:

如果您对awk 满意,请尝试关注。

byobu_line='bash "$HOME/byobu.sh"'
awk -v var="$byobu_line" '$0 == var && !found{$0="#"$0;found=1} 1' Input_file


编辑: 为了避免$HOME 的扩展,我想出了一个想法,请您尝试关注一下,稍后会添加解释(在我吃完晚饭后:) )。

这里是 Input_file:

cat file
qwe asd qwe
bash "$HOME/byobu.sh"
bash "$HOME/byobu.sh"
# asd yxc asd

这是脚本:

cat file.ksh
HOME="/home/ubuntu"    ##Setting value for testing purposes, to make sure they are NOT getting expanded.
byobu_line='bash "$HOME/byobu.sh"'
byobu_line_new=$(echo "${byobu_line//$/}")
awk -v var="$byobu_line_new" 'BEGIN{sub(/HOME/,"$&",var)} $0 == var && !found{$0="#"$0;found=1} 1' Input_file

请在我上面的awk 代码行中附加> temp && mv temp Input_file,它会将输出保存到 Input_file 本身。

解释: 编辑代码我正在做的是,我正在使用 shell 的参数扩展来创建名为 byobu_line_new 的变量,它没有 $。现在,当相同的变量在var 变量中传递给awk 并且在读取BEGIN 部分中的Input_file 之前,我再次使用替换在HOME 之前获取$。这只是为了消除变量扩展的影响(作为一种解决方法)。

对于awk 代码:我已将shell 变量byobu_line_new 传递给名为var 的变量awk,然后在BEGIN 部分中,我用变量中的$HOME 替换HOME(我之前删除了上面提到的),现在当 Input_file 获得读取检查条件时,如果 $0(current line) 等于 var 并且变量 found 未设置(这只会在第一次匹配时发生,因为当匹配 var==$0找到意味着您的 shell 变量在行中找到,然后将变量 found 设置为 1,因此下次此条件将不为真)。然后提到 1 将从 Input_file 打印已编辑/未编辑的行(因为 awk 适用于模式方法然后操作,我通过提及 1 使条件为 TRUE 并且没有给出任何操作,因此默认情况下会打印行) .

【讨论】:

    【解决方案2】:

    您使用sed 的尝试非常接近。 0,/match/s/find/replace/ 形式的使用是正确的,但您需要稍作修改:

    sed '0,/^bash\ "\/home\/david\/byobu.sh"$/s/^bash\ "\/home\/david\/byobu.sh"$/# bash\ "\/home\/david\/byobu.sh"$/' file
    

    0,addr2 的使用导致 sed"matched first address" state 中开始,因此当找到 addr2 时,表达式将位于其范围的末尾,进行一次替换,然后再次不匹配仅匹配第一次出现的效果。

    您完全错误地认为您需要搜索以'\n' 开头的行。这不是sed 的工作方式。行不以'\n' 字符开头。

    在表达式bash "/home/david/byobu.sh" 中,您应该分别用'^''$' 锚定开头和结尾,这样您就不会同时匹配较大行的包含较少的子字符串。

    对于替换,您只需在带有s/^bash\ "\/home\/david\/byobu.sh"$/# bash\ "\/home\/david\/byobu.sh"$/ 的行的开头插入"# "。出于同样的原因,您需要锚定 0,/addr2/ 术语,您也应该充分描述和锚定替换术语。

    总而言之,你可以这样做:

    $ sed '0,/^bash\ "\/home\/david\/byobu.sh"$/s/^bash\ "\/home\/david\/byobu.sh"$/# bash\ "\/home\/david\/byobu.sh"$/' file
    qwe asd qwe
    # bash "/home/david/byobu.sh"
    bash "/home/david/byobu.sh"
    # asd yxc asd
    

    这提供了您预期的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 2017-12-20
      • 1970-01-01
      相关资源
      最近更新 更多