ssh - 从Bash命令查找和替换文本文件

查找和替换给定输入字符串的最简单方法是什么,例如abc,并用另一个字符串替换,比如文件/tmp/file.txt中的XYZ

我正在编写一个应用程序并使用IronPython通过SSH执行命令 - 但我不熟悉Unix,也不知道要查找什么。

我听说Bash除了是命令行界面外,还可以是一种非常强大的脚本语言。 所以,如果这是真的,我假设您可以执行这些操作。

我可以用bash做什么,以及实现目标的最简单(一行)脚本是什么?

Ash asked 2019-01-04T19:34:37Z
14个解决方案
703 votes

最简单的方法是使用sed(或perl):

while read a ; do echo ${a//abc/XYZ} ; done < /tmp/file.txt > /tmp/file.txt.t ; mv /tmp/file.txt{.t,}

由于while read a ; do echo ${a//abc/XYZ} ; done < /tmp/file.txt > /tmp/file.txt.t ; mv /tmp/file.txt{.t,}选项,将调用sed进行就地编辑。 这可以从bash调用。

如果你真的真的想使用bash,那么以下内容可以工作:

while read a ; do echo ${a//abc/XYZ} ; done < /tmp/file.txt > /tmp/file.txt.t ; mv /tmp/file.txt{.t,}

这循环遍历每一行,进行替换,并写入临时文件(不想破坏输入)。 最后的移动只是临时移动到原始名称。

johnny answered 2019-01-04T19:35:11Z
149 votes

文件操作通常不是由Bash完成的,而是由Bash调用的程序完成的,例如:

> perl -pi -e 's/abc/XYZ/g' /tmp/file.txt

man perlrun标志告诉它进行就地替换。

有关详细信息,请参阅man perlrun,包括如何备份原始文件。

Alnitak answered 2019-01-04T19:35:46Z
59 votes

我很惊讶,因为我偶然发现了......

有一个“替换”命令随包“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替换更多内容...

rayro answered 2019-01-04T19:36:20Z
37 votes

与其他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的':'提示符下输入相同的命令。

slim answered 2019-01-04T19:37:07Z
32 votes

在其他人中找到了这个帖子,我同意它包含最完整的答案,所以我也添加了我的:

1)sed和ed非常有用......手工制作!看看@Johnny的代码:

sed -i -e 's/abc/XYZ/g' /tmp/file.txt

2)当我的限制是通过shell脚本使用它时,没有变量可以用来代替abc或XYZ! 这似乎与我至少理解的一致。 所以,我不能用:

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说使用'while 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
......

3)因为可以看到是否设置了nullglob,当有一个包含*的字符串时它会表现得很奇怪

<VirtualHost *:80>
 ServerName www.example.com

变成了

<VirtualHost ServerName www.example.com

没有结束角括号,Apache2甚至无法加载!

4)这种解析应该比单击搜索和替换慢,但是,正如您已经看到的,4个不同的搜索模式有4个变量在一个解析周期中运行!

在给定的问题假设下,我能想到最合适的解决方案。

centurian answered 2019-01-04T19:38:23Z
31 votes

这是一个老帖子,但对于任何想要使用变量的人来说,@ centurian说单引号意味着什么都不会扩展。

获取变量的一种简单方法是进行字符串连接,因为这是通过bash中的并置完成的,以下应该可以工作:

sed -i -e 's/'"$var1"'/'"$var2"'/g' /tmp/file.txt

zcourts answered 2019-01-04T19:38:57Z
12 votes

你可以使用sed

sed -i 's/abc/XYZ/gi' /tmp/file.txt

如果您不确定要查找的文本是abc还是ABC或AbC,请使用i忽略大小写,...

如果你现在没有你的文件名,你可以使用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' {} \;
MmParvin answered 2019-01-04T19:39:40Z
11 votes

您还可以使用ed命令进行文件内搜索和替换:

# delete all lines matching foobar 
ed -s test.txt <<< $'g/foobar/d\nw' 

在bash-hackers网站上查看更多信息

olegtaranenko answered 2019-01-04T19:40:07Z
7 votes

如果用“/”字符替换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]

Linux4you answered 2019-01-04T19:40:43Z
5 votes

如果您正在处理的文件不是那么大,并暂时将其存储在变量中没有问题,那么您可以立即对整个文件使用Bash字符串替换 - 不需要逐行检查:

file_contents=$(</tmp/file.txt)
echo "${file_contents//abc/XYZ}" > /tmp/file.txt

整个文件内容将被视为一个长字符串,包括换行符。

XYZ可以是变量,例如$replacement,这里不使用sed的一个优点是你不必担心搜索或替换字符串可能包含sed模式分隔符(通常,但不一定是/)。 缺点是无法使用正则表达式或任何sed更复杂的操作。

johnraff answered 2019-01-04T19:41:19Z
3 votes

要以非交互方式编辑文件中的文本,您需要就地文本编辑器,如vim。

以下是如何从命令行使用它的简单示例:

vim -esnc '%s/foo/bar/g|:wq' file.txt

这相当于ex编辑器的@slim答案,基本上是相同的。

这里有几个实际的例子foo

用文件中的bar替换文本foo

ex -s +%s/foo/bar/ge -cwq file.txt

删除多个文件的尾随空格:

ex +'bufdo!%s/\s\+$//e' -cxa *.txt

也可以看看:

  • 如何以非交互方式编辑文件(例如在管道中)? 在Vi SE
kenorb answered 2019-01-04T19:42:22Z
3 votes

找到./-type f -name“file * .txt”| xargs sed -i -e's / abc / xyz / g'

J Ajay answered 2019-01-04T19:42:44Z
1 votes

您可以使用rpl命令。 例如,您想要在整个php项目中更改域名。

rpl -ivRpd -x'.php' 'old.domain.name' 'new.domain.name' ./path_to_your_project_folder/  

这不是原因,但它是一个非常快速和有用的。:)

zalex answered 2019-01-04T19:43:13Z
1 votes

您也可以在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()
micalith answered 2019-01-04T19:43:34Z
translate from https://stackoverflow.com:/questions/525592/find-and-replace-inside-a-text-file-from-a-bash-command