【问题标题】:first replacement of a string in a file using sed使用 sed 首次替换文件中的字符串
【发布时间】:2011-08-10 04:14:18
【问题描述】:

我想知道如何替换整个文件中第一次出现的搜索模式。例如,

import java.io.File;
import java.io.File;

应该替换为

import java.io.IOException;
import java.io.File;

如何使用 sed 实现这一点? 谢谢你

【问题讨论】:

标签: bash shell unix sed replace


【解决方案1】:

我要做的是将所有行追加到一个大行中并替换内容。

$ cat f
import java.io.File;
import java.io.File;
$ sed -n 'N
  ${
    s/import java.io.File;/import java.io.IOException/
    p
  }' f
import java.io.IOException
import java.io.File;

它是如何工作的:首先,我禁止行打印,这是默认行为,将 -n 选项传递给 sed。

然后是 sed 命令。第一个是N 命令:它将一个换行符和流的下一行附加到当前行,然后保持在模式空间。这会将当前行更改为下一行,然后将追加下一行...直到文件末尾。

在文件的末尾以及在最后一行执行N 命令之后,模式空间将包含所有行。然后,在文件的末尾(由$ 地址指定)我们只需将所需的行替换为:

s/import java.io.File;/import java.io.IOException/

由于s/// 命令默认在模式空间每次迭代只替换一次,所以它只会替换第一行。现在模式空间已经替换了行,但不会打印出来,因为我们使用了-n 选项。所以,我们需要使用p 命令打印它。一旦我们将在文件末尾执行两个操作,我们使用$ 对其进行寻址,并将操作放在括号中({})。

在那里,为了清楚起见,我们只在多行中介绍了 sed 命令。我们可以在一行中使用它们;只需用分号分隔即可:

$ sed -n 'N;${s/import java.io.File;/import java.io.IOException/;p;}' f
import java.io.IOException
import java.io.File;

HTH

【讨论】:

    【解决方案2】:
    cat file | sed -e ':l
        0,/my_search_str/ {
        /my_search_str/! {
                N;
                b l
                }
        s/my_search_str/replace_this/g  
        :t
        N
        b t     
        }
        '
    

    这对我有用: 文件:(之前)

    hello1
    my_search_str
    hello2
    mysearch_str
    hello3
    

    文件:(之后)

    hello1
    replace_this
    hello2
    mysearch_str
    hello3
    

    【讨论】:

      【解决方案3】:

      如果只需要替换就可以在一行中完成所有工作,当然没有必要编写一些大而长的脚本。您只需为工作选择合适的电动工具即可。

      这是一个 Perl 单行代码:

      % cat -n /tmp/f
           1  import java.lang.Character;
           2  import java.io.File;
           3  import java.io.File;
           4  import java.util.Pattern;
      
      % perl -pe 's//IoException/ if m?import java\.io\.\KFile?' /tmp/f
      import java.lang.Character;
      import java.io.IoException;
      import java.io.File;
      import java.util.Pattern;
      

      如果您想编辑文件,只需添加 -i.bak

      % perl -i.bak -pe 's//IoException/ if m?import java\.io\.\KFile?' /tmp/f
      
      % head /tmp/f{,.bak}
      ==> /tmp/f <==
      import java.lang.Character;
      import java.io.IoException;
      import java.io.File;
      import java.util.Pattern;
      
      ==> /tmp/f.bak <==
      import java.lang.Character;
      import java.io.File;
      import java.io.File;
      import java.util.Pattern;
      

      之所以有效,是因为当您为 m// 运算符提供 ?? 分隔符时,它具有一些内置状态,需要记住仅匹配第一次。

      然后在替换中,空模式意味着重用最后匹配的模式,因此您不必再次键入它并冒着两者潜水的风险。

      最后,模式中的\K 违背了匹配,将内容“保留”在左侧,以免被替代品吞噬。

      【讨论】:

        【解决方案4】:

        您可以使用 shell 脚本 (Bash)

        #!/bin/bash
        
        declare -i toggle=0
        while read -r line
        do
                case "$line" in
                    *import*java.io.File*)
                    if [ $toggle -eq 1 ];then
                        echo "$line"
                        continue
                    fi
                    echo "import java.io.Exception";
                    toggle=1
                    continue
                    ;;
                esac
                echo "$line"
        done < file
        

        样本输出

        $> more file
        import java.util.Scanner;
        import java.io.File;
        import java.io.File;
        
        $> bash search_replace.sh
        import java.util.Scanner;
        import java.io.Exception
        import java.io.File;
        

        或者您可以将整个文件放入内存并进行一次性替换

        data=$(<file)
        echo "${data/import java.io.File;/import java.io.IOException}"
        

        【讨论】:

          【解决方案5】:

          只需在命令行中执行如下操作:

          cat text.txt |
          awk '/File/{
            if ( count < 1 ){ gsub("File","IOException")}
            count++
            print
            }'
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-11-14
            • 2021-03-01
            • 1970-01-01
            • 1970-01-01
            • 2011-10-11
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多