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

Jon*_*Doe 836 command-line text-processing

如何使用命令行查找和替换文本文件中的特定单词?

csc*_*ney 1338

sed -i 's/original/new/g' file.txt
Run Code Online (Sandbox Code Playgroud)

解释:

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

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

  • @mcExchange 如果它特别是您需要匹配的`/` 字符,您可以使用其他一些字符作为分隔符(例如`'s_old/text_new/text_g'`)。否则,您可以在任何 `$ * 之前放置一个 `\ `。[ \ ^` 获取文字字符。 (36认同)
  • MacOS 用户必须在 -i 之后添加 ''" 作为 -i https://ed.gs/2016/01/26/os-x-sed-invalid-command-code/ 的参数,以便文件覆盖。 (27认同)
  • OSX 命令 `sed -i '.bak' 's/original/new/g' file.txt` 也可以使用零长度扩展名 `sed -i '' 's/original/new/g' 文件运行.txt`,不会生成备份。 (24认同)
  • @BrianZ 就文件系统而言, sed 的输出是一个同名的新文件。它是 [常见报告的错误,但不是错误] 之一(https://www.gnu.org/software/sed/manual/sed.html#Reporting-Bugs) (4认同)
  • @Akiva 如果您在搜索中包含 [regex 特殊字符](https://www.gnu.org/software/sed/manual/html_node/Regular-Expressions.html#Regular-Expressions),`sed` 将匹配它们。如果您想改用扩展 RE,请添加一个 `-r` 标志。 (3认同)
  • 您可能希望 `s/\boriginal\b/new/g` 而不是 `s/original/new/g`(`\b` 在单词边界处匹配)仅替换整个单词。 (2认同)
  • 不确定这是否正确,但我只是在 Mac 上尝试过这个,并且必须在 regexp/replace 语句之前添加 `-e` (例如 `sed -i -e 's/orig/new/g' 文件)。 txt` (2认同)

Ser*_*nyy 58

有多种方法可以实现它。根据尝试通过字符串替换实现的复杂性以及用户熟悉的工具,某些方法可能比其他方法更受欢迎。

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

roses are red , violets are blue
This is an input.txt and this doesn't rhyme
Run Code Online (Sandbox Code Playgroud)

巴什

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
Run Code Online (Sandbox Code Playgroud)

这个小脚本不会进行就地替换,这意味着您必须将新文本保存到新文件中,并删除旧文件,或者 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 
Run Code Online (Sandbox Code Playgroud)

AWK 可以将输入文件作为参数,因此使用input.txt,做同样的事情会很容易:

awk '{sub(/blue/,"azure")}1' input.txt
Run Code Online (Sandbox Code Playgroud)

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

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

社会经济发展部

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

sed 's/blue/azure/' input.txt
Run Code Online (Sandbox Code Playgroud)

此工具的优点在于它具有就地编辑功能,您可以使用-i标志启用该编辑功能。

珀尔

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

perl -pe 's/blue/azure/' input.txt
Run Code Online (Sandbox Code Playgroud)

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

Python

这种语言非常通用,也用于各种应用程序。它有很多处理字符串的函数,其中包括replace(),所以如果你有像 一样的变量var="Hello World",你可以做var.replace("Hello","Good Morning")

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

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

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

#!/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])
Run Code Online (Sandbox Code Playgroud)

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

 $ ./myscript.py input.txt
Run Code Online (Sandbox Code Playgroud)

或者

$ python ./myscript.py input.txt
Run Code Online (Sandbox Code Playgroud)

当然,请确保它./myscript.py在您当前的工作目录中,对于第一种方式,请确保将其设置为可执行文件chmod +x ./myscript.py

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


Mar*_*ppi 37

有许多不同的方法可以做到这一点。一种是使用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
Run Code Online (Sandbox Code Playgroud)

这可能使比更有意义的另一种方式< 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
Run Code Online (Sandbox Code Playgroud)

  • 注意`cat 文件中的`cat` | sed '...'` 是不必要的。你可以直接说`sed '...' file`。 (6认同)

Avi*_*Raj 22

通过 awk 的 gsub 命令,

awk '{gsub(/pattern/,"replacement")}' file
Run Code Online (Sandbox Code Playgroud)

例子:

awk '{gsub(/1/,"0");}' file
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,所有的 1 都被 0 替换,而不管它位于哪一列。


如果要对特定列进行替换,请执行以下操作,

awk '{gsub(/pattern/,"replacement",column_number)}' file
Run Code Online (Sandbox Code Playgroud)

例子:

awk '{gsub(/1/,"0",$1);}' file
Run Code Online (Sandbox Code Playgroud)

它仅在第一列用 0 替换 1。

通过 Perl,

$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
Run Code Online (Sandbox Code Playgroud)


Ste*_*nny 22

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

ex -s -c '%s/OLD/NEW/g|x' file
Run Code Online (Sandbox Code Playgroud)
  1. % 选择所有行

  2. s 代替

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

  4. x 如果已进行更改(已更改)并退出,则写入


小智 11

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

sed -i -e 's/few/asd/g' hello.txt
Run Code Online (Sandbox Code Playgroud)

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

少数,勇敢。


asd,勇敢的人。

/g代表“全局”,意思是对整条线执行此操作。如果您省略了/g(with s/few/asd/,无论如何总是需要三个斜杠) 并few在同一行上出现两次,只有第一个few更改为asd

男人少,女人少,勇敢。


asd 男人,少数女人,勇敢的人。

这在某些情况下很有用,例如更改行开头的特殊字符(例如,用水平制表符替换一些人用来引用电子邮件线程中先前材料的大于号,同时在行的后面留下引用的代数不等式未触及),但在您指定发生的任何地方 few都应该被替换的示例中,请确保您有那个/g.

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

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

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

注意:-i -e用于搜索/替换很重要。如果这样做-ie,则为每个附加了字母“e”的文件创建备份。