对于给定的输入字符串执行查找和替换的最简单方法是什么,比如说abc
,并替换为另一个字符串,比如文件XYZ
中的/tmp/file.txt
?
我正在编写一个应用程序并使用IronPython通过SSH执行命令 - 但我不熟悉Unix,也不知道要查找什么。
我听说Bash除了是一个命令行界面外,还可以是一个非常强大的脚本语言。所以,如果这是真的,我假设您可以执行这些操作。
我能用bash做什么,以及实现目标的最简单(一行)脚本是什么?
答案 0 :(得分:802)
最简单的方法是使用sed(或perl):
sed -i -e 's/abc/XYZ/g' /tmp/file.txt
由于-i
选项,会调用sed进行就地编辑。这可以从bash调用。
如果你真的真的想要使用bash,那么以下内容可以起作用:
while read a ; do echo ${a//abc/XYZ} ; done < /tmp/file.txt > /tmp/file.txt.t ; mv /tmp/file.txt{.t,}
这循环遍历每一行,进行替换,并写入临时文件(不想破坏输入)。最后的移动只是临时移动到原始名称。
答案 1 :(得分:156)
文件操作通常不是由Bash完成的,而是由Bash调用的程序完成的,例如:
> perl -pi -e 's/abc/XYZ/g' /tmp/file.txt
-i
标志告诉它进行就地替换。
有关详细信息,请参阅man perlrun
,包括如何备份原始文件。
答案 2 :(得分:65)
我很惊讶,因为我偶然发现了......
“替换”命令附带“mysql-server”包,所以如果你已安装它,请试试看:
# replace string abc to XYZ in files
replace "abc" "XYZ" -- file.txt file2.txt file3.txt
# or pipe an echo to replace
echo "abcdef" |replace "abc" "XYZ"
有关详情,请参阅 man replace ...
答案 3 :(得分:40)
这是一个老帖子,但是对于任何想要使用变量的人来说@centurian说单引号意味着什么都不会扩展。
获取变量的一种简单方法是进行字符串连接,因为这是通过bash中的并置完成的,以下内容应该有效:
sed -i -e 's/'"$var1"'/'"$var2"'/g' /tmp/file.txt
答案 4 :(得分:38)
与其他shell一样,Bash只是一种协调其他命令的工具。通常,您会尝试使用标准的UNIX命令,但您当然可以使用Bash来调用任何内容,包括您自己编译的程序,其他shell脚本,Python和Perl脚本等。
在这种情况下,有几种方法可以做到。
如果您想要读取文件并将其写入另一个文件,请在进行搜索/替换时使用sed:
sed 's/abc/XYZ/g' <infile >outfile
如果你想编辑文件(好像在编辑器中打开文件,编辑它,然后保存它),请向行编辑器'ex'提供说明
echo "%s/abc/XYZ/g
w
q
" | ex file
Ex就像没有全屏模式的vi。您可以使用与vi'''提示相同的命令。
答案 5 :(得分:32)
在其他人中找到了这个帖子,我同意它包含最完整的答案,所以我也添加了它:
1)sed和ed非常有用......手工制作! 看看@Johnny的代码:
sed -i -e 's/abc/XYZ/g' /tmp/file.txt
2)当我的限制是通过shell脚本使用它时,没有变量可以用来代替abc或XYZ! This似乎同意我至少理解的内容。所以,我无法使用:
x='abc'
y='XYZ'
sed -i -e 's/$x/$y/g' /tmp/file.txt
#or,
sed -i -e "s/$x/$y/g" /tmp/file.txt
但是,我们能做什么?至于@Johnny说,在阅读时使用&#39;&#39;但不幸的是,这不是故事的结局。以下与我合作很好:
#edit user's virtual domain
result=
#if nullglob is set then, unset it temporarily
is_nullglob=$( shopt -s | egrep -i '*nullglob' )
if [[ is_nullglob ]]; then
shopt -u nullglob
fi
while IFS= read -r line; do
line="${line//'<servername>'/$server}"
line="${line//'<serveralias>'/$alias}"
line="${line//'<user>'/$user}"
line="${line//'<group>'/$group}"
result="$result""$line"'\n'
done < $tmp
echo -e $result > $tmp
#if nullglob was set then, re-enable it
if [[ is_nullglob ]]; then
shopt -s nullglob
fi
#move user's virtual domain to Apache 2 domain directory
......
3)如果可以看到是否设置了nullglob,当存在包含*的字符串时,它会表现得很奇怪,如
<VirtualHost *:80>
ServerName www.example.com
成为
<VirtualHost ServerName www.example.com
没有结束角括号,Apache2甚至无法加载!
4)这种解析应该比单击搜索和替换慢,但是,正如您已经看到的,4个不同的搜索模式有4个变量在一个解析周期中运行!
我可以根据问题的假设来考虑最合适的解决方案。
答案 6 :(得分:19)
您可以使用sed
method_missing': undefined local variable or method
如果您不确定要查找的文字是sed -i 's/abc/XYZ/gi' /tmp/file.txt
还是-i
还是abc
等,请使用ABC
忽略大小写。
如果您现在没有文件名,可以使用AbC
和find
:
sed
查找并替换所有python文件:
find ./ -type f -exec sed -i 's/abc/XYZ/gi' {} \;
答案 7 :(得分:11)
您也可以使用ed命令进行文件内搜索和替换:
# delete all lines matching foobar
ed -s test.txt <<< $'g/foobar/d\nw'
答案 8 :(得分:8)
如果用“/”字符替换URL,请小心。
如何做的一个例子:
sed -i "s%http://domain.com%http://www.domain.com/folder/%g" "test.txt"
摘自:http://www.sysadmit.com/2015/07/linux-reemplazar-texto-en-archivos-con-sed.html
答案 9 :(得分:7)
如果您正在处理的文件不是那么大,并暂时将其存储在变量中是没有问题的,那么您可以立即对整个文件使用Bash字符串替换 - 没有必要过去它逐行:
file_contents=$(</tmp/file.txt)
echo "${file_contents//abc/XYZ}" > /tmp/file.txt
整个文件内容将被视为一个长字符串,包括换行符。
XYZ可以是变量,例如$replacement
,这里不使用sed的一个好处是你不必担心搜索或替换字符串可能包含sed模式分隔符(通常,但不一定, /)。缺点是无法使用正则表达式或任何更复杂的操作。
答案 10 :(得分:4)
要以非交互方式编辑文件中的文本,您需要使用就地文本编辑器,例如vim。
以下是如何从命令行使用它的简单示例:
vim -esnc '%s/foo/bar/g|:wq' file.txt
这相当于@slim answer编辑器的ex,基本上是相同的。
以下是一些ex
实例。
用文件中的foo
替换文字bar
:
ex -s +%s/foo/bar/ge -cwq file.txt
删除多个文件的尾部空格:
ex +'bufdo!%s/\s\+$//e' -cxa *.txt
故障排除(当终端卡住时):
-V1
参数以显示详细消息。-cwq!
。另见:
答案 11 :(得分:4)
尝试以下shell命令:
find ./ -type f -name "file*.txt" | xargs sed -i -e 's/abc/xyz/g'
答案 12 :(得分:2)
您也可以在bash脚本中使用python。我在这里得到的一些顶级答案并没有太大成功,并且发现这可以在不需要循环的情况下工作:
#!/bin/bash
python
filetosearch = '/home/ubuntu/ip_table.txt'
texttoreplace = 'tcp443'
texttoinsert = 'udp1194'
s = open(filetosearch).read()
s = s.replace(texttoreplace, texttoinsert)
f = open(filetosearch, 'w')
f.write(s)
f.close()
quit()
答案 13 :(得分:1)
您可以使用rpl命令。例如,您想要在整个php项目中更改域名。
rpl -ivRpd -x'.php' 'old.domain.name' 'new.domain.name' ./path_to_your_project_folder/
这不是原因,但它是一个非常快速和有用的。 :)
答案 14 :(得分:0)
使用 sed 命令替换文件中多个文本的最简单方法
命令 -
sed -i 's#a/b/c#D/E#g;s#/x/y/z#D:/X#g;'文件名
在上面的命令 s#a/b/c#D/E#g 中,我将 a/b/c 替换为 D/E,然后在 ;我们再次做同样的事情