使用命令在文件中查找和替换文本


Answers:


1053
sed -i 's/original/new/g' file.txt

说明:

  • sed =流编辑器
  • -i =就地(即保存回原始文件)
  • 命令字符串:

    • s =替代命令
    • original =描述要替换单词(或仅单词本身)的正则表达式
    • new =替换为的文本
    • g =全局(即替换所有而不是仅替换第一个匹配项)
  • file.txt =文件名


3
@Akiva如果在搜索中包含正则表达式特殊字符sed它们将匹配它们。-r如果要使用扩展RE,请添加一个标志。
cscarney

32
@mcExchange如果/您需要专门匹配该字符,则可以使用其他一些字符作为分隔符(例如's_old/text_new/text_g')。否则,您可以\ 在任何一个之前放置a $ * . [ \ ^以获得文字字符。
cscarney

3
@BrianZ就文件系统而言,sed的输出是一个具有相同名称的新文件。这是一个不属于错误常见的错误
cscarney

16
OSX命令sed -i '.bak' 's/original/new/g' file.txt还可以使用零长度扩展名运行,该扩展名sed -i '' 's/original/new/g' file.txt不会生成任何备份。
柯克

19
MacOS的用户将不得不为-i参数后-i添加'” ed.gs/2016/01/26/os-x-sed-invalid-command-code使得该文件将被覆盖。
geoyws

32

有许多不同的方法可以做到这一点。一种是使用正则sed表达式。SED是用于过滤和转换文本的流编辑器。一个示例如下:

marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog

这可能使比更有意义的另一种方式< strin,并> strout与管!

marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai 
The quick brown fox jumped over the lazy sleeping dog

6
注意catcat file | sed '...'是不必要的。你可以直接说sed '...' file
fedorqui 2015年

1
的确,这可以进一步减少:sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarly将按年采集文件,并在进行备份时就地进行2次更改。time bash -c "$COMMAND"经常使用它建议该版本快约5倍。
pbhj

23

有多种方法可以实现它。取决于人们尝试用字符串替换实现的复杂性,并取决于用户熟悉的工具,某些方法可能比其他方法更受青睐。

在此答案中,我使用的是简单input.txt文件,您可以使用它来测试此处提供的所有示例。文件内容:

roses are red , violets are blue
This is an input.txt and this doesn't rhyme

重击

Bash并不是真正用于文本处理,但是可以通过参数扩展来进行简单替换,特别是在这里我们可以使用简单结构${parameter/old_string/new_string}

#!/bin/bash
while IFS= read -r line
do
    case "$line" in
       *blue*) printf "%s\n" "${line/blue/azure}" ;;
       *) printf "%s\n" "$line" ;;
    esac
done < input.txt

这个小脚本不会进行就地替换,这意味着您必须将新文本保存到新文件,并删除旧文件,或者 mv new.txt old.txt

旁注:如果您对为什么while IFS= read -r ; do ... done < input.txt使用它感到好奇,那基本上就是shell逐行读取文件的方式。请参阅作为参考。

AWK

AWK是一种文本处理实用程序,非常适合此类任务。它可以根据正则表达式进行简单的替换,也可以进行更高级的替换。它提供了两个功能:sub()gsub()。第一个仅替换第一个匹配项,而第二个-替换整个字符串中的匹配项。例如,如果我们有string one potato two potato,这将是结果:

$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana

$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'                                      
one banana two potato 

AWK可以将输入文件作为参数,因此使用进行相同的操作input.txt很容易:

awk '{sub(/blue/,"azure")}1' input.txt

根据您拥有的AWK版本,它可能会或可能不会就地编辑,因此通常的做法是保存并替换新文本。例如这样的事情:

awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt

SED

Sed是行编辑器。它还使用了正则表达式,但是对于简单的替换,就足够了:

sed 's/blue/azure/' input.txt

该工具的优点是它具有就地编辑功能,您可以使用-iflag 启用它。

佩尔

Perl是另一种经常用于文本处理的工具,但是它是一种通用语言,并且用于网络,系统管理,桌面应用程序以及许多其他地方。它从其他语言(例如C,sed,awk等)中借用了许多概念/功能。可以这样简单替换:

perl -pe 's/blue/azure/' input.txt

像sed一样,perl也具有-i标志。

蟒蛇

该语言用途广泛,还可以用于多种应用中。它有很多处理字符串的功能,其中有个replace(),因此,如果您有变量like var="Hello World",则可以var.replace("Hello","Good Morning")

读取文件并替换其中的字符串的简单方法如下:

python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt

但是,使用Python,您还需要输出到new文件,也可以从脚本本身内部执行此操作。例如,这是一个简单的例子:

#!/usr/bin/env python
import sys
import os
import tempfile

tmp=tempfile.mkstemp()

with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
    for line in fd1:
        line = line.replace('blue','azure')
        fd2.write(line)

os.rename(tmp[1],sys.argv[1])

该脚本将input.txt作为命令行参数来调用。使用命令行参数运行python脚本的确切命令是

 $ ./myscript.py input.txt

要么

$ python ./myscript.py input.txt

当然,请确保该文件./myscript.py位于您当前的工作目录中,并且首先要确保将其设置为可执行文件,chmod +x ./myscript.py

Python也可以具有正则表达式,特别是re模块,该模块具有re.sub()功能,可以用于更高级的替换。


1
不错的编译!此处未提及的另一种可能方法是tr在Unix中使用命令
Tapajit Dey,

1
@TapajitDey是的,tr 是另一种伟大的工具,但要注意,它是替代字符集(例如tr abc cde将转化acbd是从更换整个单词与有点不同。sed或者python
谢尔盖Kolodyazhnyy

22

您可以在Ex模式下使用Vim:

ex -s -c '%s/OLD/NEW/g|x' file
  1. % 选择所有行

  2. s 替代

  3. g 替换每一行中的所有实例

  4. x 写(如果有)更改并退出


21

通过awk的gsub命令,

awk '{gsub(/pattern/,"replacement")}' file

例:

awk '{gsub(/1/,"0");}' file

在上面的示例中,所有1均被0取代,无论其位于哪一列。


如果您想在特定的列上进行替换,请按照以下步骤操作:

awk '{gsub(/pattern/,"replacement",column_number)}' file

例:

awk '{gsub(/1/,"0",$1);}' file

仅在第一列上将1替换为0。

通过Perl,

$ echo 'foo' | perl -pe 's/foo/bar/g'
bar

我在MacOS终端上使用了它,却什么也没做……
Jim

在Alpine Linux(在Docker容器中)上进行了测试,但没有输出
SalathielGenèse18年

@SalathielGenèse您想达到什么目的?
Avinash Raj

我正在env inotifywait下观看文件sh,并以CSV格式报告数据(因为自定义格式存在错误)。然后,我发现没有简单的方法可以在Shell脚本中处理CSV文档...而且我希望它非常轻巧。因此,我启动了一个非常简单的脚本来分析和报告CSV。我阅读了CSV规范,发现它比我预期的要复杂得多,并且支持用双引号引起来的多行值。我曾经依赖于sed标记化,但是很快就意识到,甚至所谓的sed多行也最多包含两行。如果我的CSV值之一跨越两行以上怎么办?
SalathielGenèse18年

最好将您的问题作为问题提出。
Avinash Raj

8

sed小号 tream itor中,你可以使用|(管)发送标准流通过(STDIN和STDOUT明确)sed和编程改变它们的飞行,使得它在Unix哲学传统的一个方便的工具; 但也可以使用-i下面提到的参数直接编辑文件。
考虑以下几点

sed -i -e 's/few/asd/g' hello.txt

s/用于小号 ubstitute所找到的表达fewasd

少数,勇敢。


asd,勇敢。

/g代表“全局”,表示针对整行执行此操作。如果不使用/g(带有s/few/asd/,无论如何总是需要三个斜杠)并且few在同一行上出现两次,则只有第一个few变为asd

几个男人,几个女人,勇敢。


asd男人,几个女人,勇敢。

在某些情况下,这很有用,例如在行首更改特殊字符(例如,用水平制表符替换某些人用来在电子邮件线程中引用以前材料的大于号,同时在行后保留带引号的代数不等式未修改),但在您指定应替换掉任何地方的 示例中,请few确保您具有/g

以下两个选项(标志)组合为一个-ie

-i选项用于编辑 N将在文件上hello.txt

-e选项指示ë XPRESSION /命令来运行,在这种情况下s/

注意:使用-i -e搜索/替换很重要。如果这样做-ie,您将为每个文件创建备份,并添加字母“ e”。


2

您可以这样:

locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g" 

示例:将由locate命令产生的所有文件中的所有出现的[logdir',''](不带[])替换为[logdir',os.getcwd()],请执行以下操作:

例1:

locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"

例2:

locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"

[tensorboard / program.py]是要搜索的文件


你好 您选择的字符串(logdir', ''-> /logdir', os.getcwd())使此答案难以解析。另外,值得指定您的答案首先找到要使用sed的文件,因为这不是问题的一部分。
mwfearnley

嗨,答案是搜索并替换所有文件,如果它在文件中找到<old text>。
阮·安·安

我为他们在keras中使用tensorboard的所有人选择了这个答案,他们希望将命令从以下位置更改:tensorboard --logdir ='/ path / to / log / folder /'使用:仅当保存在logs文件夹中时,才能使用tensorboard。这是非常方便
阮·安·安
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.