【问题标题】:Linux sed command does not change the target fileLinux sed 命令不改变目标文件
【发布时间】:2013-01-17 20:02:22
【问题描述】:

使用我的 shell 脚本,当我运行 ./Test1 hello result.

它应该将hello 作为标准输入,并将结果作为标准输出。 shell 应该删除<td></td>abc 之前的所有空格

所以,我这样写脚本

tr -d [:blank:] < $1
grep -r "<td>" $1 | sed -r 's/<td>//g' > $2
sed -r 's/<\/td>//g' $2
sed -r 's/abc//g' $2

但是,当我运行此命令时,结果文件的内容与 hello 文件的内容完全相同(唯一的区别是删除了空格)

文件hello内容:

<td>hello</td>
  <td>hello</td>
    <td>hello</td>
<td>abc</td>
 <td>abc</td>

如何让sed 将更改应用到目标文件?

【问题讨论】:

    标签: regex linux sed


    【解决方案1】:

    如果您想将sed 的更改存储回文件,请使用-i 选项:

    $ cat file
    <head>abc</head>
        <td>hello</td>
          <td>hello</td>
            <td>hello</td>
        <td>abc</td>
         <td>abc</td>
    <h1>abc</h1>
    
    $ sed -ni '/<td>/{s/^\s*//;s/abc//;s/<\/\?td>//g;p}' file
    
    $ cat file
    hello
    hello
    hello
    

    编辑:如果我们在sed 中使用不同的分隔符并使用扩展的正则表达式选项-r,则正则表达式会更清晰:

    $ sed -r 's_</?td>__g' file
        hello
          hello
            hello
        abc
         abc
    

    ? 使前一个字符可选,因此不必存在/,从而使正则表达式匹配&lt;td&gt;&lt;/td&gt; 合二为一。

    【讨论】:

    • 什么是 ?和 有什么不同吗?
    • 另外,我使用了grep,因为hello是一个html文件,所以有等,所以,我想在文件中找到包含的行,删除 ,然后把它放在 $2 文件中。很抱歉造成混乱
    • 另见编辑只匹配包含&lt;td&gt;的行替换grep的需要。
    • 那么,你的意思是我必须手动删除那个 吗?也使用 sed?起初,我使用 grep 是因为它会跳转到仅包含 的行并将其放入输出文件中。 (因此, 不会被写入输出文件。
    • @user1988385 啊,你现在的意思更清楚了,看看新的编辑,如果有帮助,考虑接受这个答案。
    【解决方案2】:

    在 sed 命令中使用 -i 选项来更改文件本身,如果没有,则在屏幕上打印输出但文件保持不变。

    公式是:

    sed -i <targetFile> 's/<beforeText>/<afterText>/g' <targetFile>
    

    例如:

    sed -i myCredentials.txt 's/secretPassword/xxx/g' myCredentials.txt
    

    另一个选项 - 输出到另一个文件并重命名:

    sed 's/secretPassword/xxx/g' myCredentials.txt > temp.txt
    rm myCredentials.txt && mv temp.txt myCredentials.txt
    

    有关更多信息,请查看文档:

    sed 实用程序读取指定的文件,如果没有则读取标准输入 文件被指定,修改输入的列表指定的com- 要求。然后将输入写入标准输出。 可以将单个命令指定为 sed 的第一个参数。多 可以使用 -e 或 -f 选项指定命令。所有命令 以指定的顺序应用于输入,而不管 他们的起源。

    -i 就地编辑文件,以指定的扩展名保存备份。 如果给出零长度扩展名,则不会保存备份。它 不建议在就地时给出零长度扩展 编辑文件,因为您有损坏或部分内容的风险 - 磁盘空间耗尽等情况。

    【讨论】:

      【解决方案3】:

      如果您希望sed 编辑现有文件,您应该给它-i 选项。

      UPD:不清楚你想对tr 的结果做什么(现在它进入脚本的标准输出,是有意的吗?)

      【讨论】:

      • 所以你的意思是我应该这样做: tr -d [:blank:] $2 -----> 删除 $1 中的所有空白并将结果放入 $2?另外, sed -i '....'
      • 是的,但请查看@sudo_O 的答案,以获得彻底改进的解决方案(一切都在 sed 中完成)。顺便说一句,\/\? 代表“可选斜杠”,即/ 或什么都没有,以同时匹配&lt;td&gt;&lt;/td&gt;
      【解决方案4】:

      grep 解决方案:

      kent$  echo "<td>hello</td>
        <td>hello</td>
          <td>hello</td>
      <td>abc</td>
       <td>abc</td>"|grep -v 'abc'|grep -oP '(?<=<td>).*(?=</td>)'                                                                                                                
      hello
      hello
      hello
      

      awk 解决方案:

      kent$  echo "<td>hello</td>
        <td>hello</td>
          <td>hello</td>
      <td>abc</td>
       <td>abc</td>"|awk -F"</?td>" '!/abc/{print $2}'
      hello
      hello
      hello
      

      【讨论】:

        【解决方案5】:

        您只需要 1 条简单的 sed 或 awk 替换行:

        sed -r 's/[[:blank:]]|<\/?td>|abc//g' file
        awk '{gsub(/[[:blank:]]|<\/?td>|abc/,"")}1' file
        

        例如:

        $ cat file
        <td>hello</td>
          <td>hello</td>
            <td>hello</td>
        <td>abc</td>
         <td>abc</td>
        
        $ sed -r 's/[[:blank:]]|<\/?td>|abc//g' file
        hello
        hello
        hello
        

        【讨论】:

          【解决方案6】:

          如果要sed修改文件需要通过-e

          【讨论】:

          • 您将-e 传递给哪个命令以便就地编辑? (答案是'问题中没有提到',很遗憾!)grep 命令采用-e,但它指定了要搜索的正则表达式。 sed 命令采用 -e,但它指定了脚本(的片段)。
          猜你喜欢
          相关资源
          最近更新 更多
          热门标签