首先使用sed替换文件中的字符串

时间:2011-04-21 09:35:04

标签: bash shell unix sed replace

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

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

应替换为

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

如何使用sed实现这一目标? 谢谢

5 个答案:

答案 0 :(得分:2)

当它只需要替换来完成一行中的所有工作时,当然不需要编写一些大的长脚本。您只需为工作选择合适的电动工具。

这是一个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违背了匹配,“保留”左边的内容,以便它不会被替代品吞噬。

答案 1 :(得分: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

答案 2 :(得分: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

答案 3 :(得分:0)

您可以使用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}"

答案 4 :(得分:0)

只需在命令行上执行,如下所示:

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