对给定的输入字符串进行查找和替换的最简单方法是什么,比如在文件中abc
替换为另一个字符串?XYZ
/tmp/file.txt
我正在编写一个应用程序并使用 IronPython 通过 SSH 执行命令——但我不太了解 Unix,也不知道要寻找什么。
我听说 Bash 除了作为命令行界面之外,还可以是一种非常强大的脚本语言。所以,如果这是真的,我假设你可以执行这样的操作。
我可以用 bash 来做吗,实现我的目标的最简单(一行)脚本是什么?
对给定的输入字符串进行查找和替换的最简单方法是什么,比如在文件中abc
替换为另一个字符串?XYZ
/tmp/file.txt
我正在编写一个应用程序并使用 IronPython 通过 SSH 执行命令——但我不太了解 Unix,也不知道要寻找什么。
我听说 Bash 除了作为命令行界面之外,还可以是一种非常强大的脚本语言。所以,如果这是真的,我假设你可以执行这样的操作。
我可以用 bash 来做吗,实现我的目标的最简单(一行)脚本是什么?
最简单的方法是使用 sed(或 perl):
sed -i -e 's/abc/XYZ/g' /tmp/file.txt
-i
由于该选项,它将调用 sed 进行就地编辑。这可以从 bash 中调用。
如果您真的真的只想使用 bash,那么以下方法可以工作:
while IFS='' read -r a; do
echo "${a//abc/XYZ}"
done < /tmp/file.txt > /tmp/file.txt.t
mv /tmp/file.txt{.t,}
这会遍历每一行,进行替换,然后写入临时文件(不想破坏输入)。最后的移动只是临时移动到原始名称。(为了稳健性和安全性,临时文件名不应该是静态的或可预测的,但我们不要去那里。)
sed -i '' 's/abc/XYZ/g' /tmp/file.txt
(请参阅下面的评论为什么)
文件操作通常不是由 Bash 完成,而是由 Bash 调用的程序完成,例如:
perl -pi -e 's/abc/XYZ/g' /tmp/file.txt
该-i
标志告诉它进行就地替换。
有关man perlrun
更多详细信息,包括如何备份原始文件,请参阅。
当我偶然发现这个时,我很惊讶...
replace
软件包附带了一个命令"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
更多信息,请参阅。
这是一篇旧帖子,但对于任何想要使用变量的人来说,@centurian 说单引号意味着什么都不会被扩展。
获取变量的一种简单方法是进行字符串连接,因为这是通过 bash 中的并置完成的,以下应该可以工作:
sed -i -e "s/$var1/$var2/g" /tmp/file.txt
Bash 和其他 shell 一样,只是一个协调其他命令的工具。通常你会尝试使用标准的 UNIX 命令,但你当然可以使用 Bash 来调用任何东西,包括你自己编译的程序、其他 shell 脚本、Python 和 Perl 脚本等。
在这种情况下,有几种方法可以做到这一点。
如果您想读取一个文件,并将其写入另一个文件,同时进行搜索/替换,请使用 sed:
sed 's/abc/XYZ/g' <infile >outfile
如果您想就地编辑文件(就像在编辑器中打开文件,编辑它,然后保存它),请向行编辑器“ex”提供说明
echo "%s/abc/XYZ/g
w
q
" | ex file
示例就像vi
没有全屏模式。你可以在vi
's:
提示符下给它同样的命令。
我发现了这个线程,我同意它包含最完整的答案,所以我也添加了我的:
sed
并且ed
非常有用......手工制作。看看@Johnny 的这段代码:
sed -i -e 's/abc/XYZ/g' /tmp/file.txt
当我的限制是在 shell 脚本中使用它时,不能在内部使用任何变量来代替“abc”或“XYZ”。BashFAQ似乎至少与我的理解一致。所以,我不能使用:
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 所说,使用 awhile read...
但是,不幸的是,这并不是故事的结局。以下对我很有效:
#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
......
正如人们所看到的那样,如果nullglob
设置了,当有一个包含 a 的字符串时,它的行为很奇怪*
:
<VirtualHost *:80>
ServerName www.example.com
变成
<VirtualHost ServerName www.example.com
没有结束尖括号,Apache2 甚至无法加载。
这种解析应该比一次性搜索和替换要慢,但是,正如您已经看到的,在一个解析周期内有四种不同的搜索模式有四个变量。
对于给定的问题假设,我能想到的最合适的解决方案。
您可以使用sed
:
sed -i 's/abc/XYZ/gi' /tmp/file.txt
如果您不知道文件名find
,您可以使用:sed
find ./ -type f -exec sed -i 's/abc/XYZ/gi' {} \;
在所有 Python 文件中查找和替换:
find ./ -iname "*.py" -type f -exec sed -i 's/abc/XYZ/gi' {} \;
如果用“/”字符替换 URL,请小心。
如何做到这一点的一个例子:
sed -i "s%http://domain.com%http://www.domain.com/folder/%g" "test.txt"
摘自:http ://www.sysadmit.com/2015/07/linux-remplazar-texto-en-archivos-con-sed.html
如果您正在处理的文件不是那么大,并且将其临时存储在变量中没有问题,那么您可以一次对整个文件使用 Bash 字符串替换 - 无需逐行检查:
file_contents=$(</tmp/file.txt)
echo "${file_contents//abc/XYZ}" > /tmp/file.txt
整个文件内容将被视为一个长字符串,包括换行符。
XYZ 可以是变量,例如$replacement
,这里不使用 sed 的一个优点是您不必担心搜索或替换字符串可能包含 sed 模式分隔符(通常但不一定是 /)。一个缺点是不能使用正则表达式或 sed 的任何更复杂的操作。
您还可以使用该ed
命令进行文件内搜索和替换:
# delete all lines matching foobar
ed -s test.txt <<< $'g/foobar/d\nw'
在“通过脚本编辑文件ed
”中查看更多信息。
要以非交互方式编辑文件中的文本,您需要就地文本编辑器,例如 vim。
这是如何从命令行使用它的简单示例:
vim -esnc '%s/foo/bar/g|:wq' file.txt
这里有几个ex
实际的例子。
将文件中的文本替换foo
为bar
:
ex -s +%s/foo/bar/ge -cwq file.txt
删除多个文件的尾随空格:
ex +'bufdo!%s/\s\+$//e' -cxa *.txt
故障排除(终端卡住时):
-V1
参数以显示详细消息。-cwq!
。也可以看看:
尝试以下 shell 命令:
find ./ -type f -name "file*.txt" | xargs sed -i -e 's/abc/xyz/g'
您也可以在 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()
使用 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,然后在 ; 我们再次做同样的事情
您可以使用 rpl 命令。例如,您想在整个 php 项目中更改域名。
rpl -ivRpd -x'.php' 'old.domain.name' 'new.domain.name' ./path_to_your_project_folder/
这不是明确的原因,但它非常快速且有用。:)
对于 MAC 用户,以防您不阅读评论 :)
正如@Austin 所述,如果您收到Invalid command code
错误消息
对于就地替换,BSD sed
需要-i
标志后的文件扩展名以保存到具有给定扩展名的备份文件。
sed -i '.bak' 's/find/replace' /file.txt
''
如果要跳过备份,可以使用空字符串。
sed -i '' 's/find/replace' /file.txt
@Austin 的所有优点
如果一起对多个文件进行更改,我们可以在一行中执行以下操作:-
user_name='whoami'
for file in file1.txt file2.txt file3.txt; do sed -i -e 's/default_user/${user_name}/g' $file; done
添加如果以防万一可能有用。