【发布时间】: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
我想知道如何替换整个文件中第一次出现的搜索模式。例如,
import java.io.File;
import java.io.File;
应该替换为
import java.io.IOException;
import java.io.File;
如何使用 sed 实现这一点? 谢谢你
【问题讨论】:
标签: bash shell unix sed replace
我要做的是将所有行追加到一个大行中并替换内容。
$ 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
【讨论】:
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
【讨论】:
如果只需要替换就可以在一行中完成所有工作,当然没有必要编写一些大而长的脚本。您只需为工作选择合适的电动工具即可。
这是一个 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 违背了匹配,将内容“保留”在左侧,以免被替代品吞噬。
【讨论】:
您可以使用 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}"
【讨论】:
只需在命令行中执行如下操作:
cat text.txt |
awk '/File/{
if ( count < 1 ){ gsub("File","IOException")}
count++
print
}'
【讨论】: