当前位置: 首页>>技术问答>>正文


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

, ,

问题描述

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

最佳解决办法

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

说明:

  • sed =流式编辑器

  • -i = in-place(即保存回原始文件)

  • 命令字符串:

    • s =替代命令

    • original =描述要替换的单词的正则表达式(或者仅仅是单词本身)

    • new =要替换的文本

    • g =全局(即全部替换而不仅仅是第一次出现)

  • file.txt =文件名

次佳解决办法

有很多不同的方法可以做到这一点。一种是使用sed和Regex。 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

第三种解决办法

通过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代替1。

通过Perl,

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

第四种办法

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

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

  2. s替代品

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

  4. x写入是否有更改(他们有)并退出

第五种办法

有很多方法可以实现它。取决于用串替换实现的复杂性以及取决于用户熟悉的工具,一些方法可能比其他方法更受欢迎。

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

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

BASH

Bash并非真正用于文本处理,而是简单的替换可以通过parameter expansion完成,特别是在这里我们可以使用简单的结构${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

这个小脚本不会执行in-place替换,这意味着您将不得不将新文本保存到新文件中,并删除旧文件或mv new.txt old.txt

注意:如果您对使用while IFS= read -r ; do ... done < input.txt的原因感到好奇,它基本上是shell逐行读取文件的方式。请参阅this以供参考。

AWK

作为文本处理工具的AWK非常适合这样的任务。它可以做简单的替换和基于regular expressions的更先进的替换。它提供了两个功能:sub()gsub()。第一个只替换第一个事件,而第二个替换整个字符串中的事件。例如,如果我们有字符串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版本,它可能会或可能不会有in-place编辑,因此通常的做法是保存并替换新文本。比如像这样的东西:

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

SED

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

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

这个工具的好处在于它具有in-place编辑功能,您可以使用-i标志启用它。

Perl

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

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

像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

但是,对于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])

此脚本将作为命令行参数与input.txt一起调用。

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

第六种办法

sed是流编辑器,因为您可以使用|(管道)通过sed发送标准流(STDIN和STDOUT),并通过编程方式实时更改它们,使其成为Unix哲学传统中的便捷工具;但也可以使用下面提到的-i参数直接编辑文件。考虑以下:

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

s/用于用asd替代找到的表达式few

The few, the brave.


The asd, the brave.

/g代表”global”,意思是为整条生产线做这件事。如果您离开/g(使用s/few/asd/,无论如何都始终需要三个斜杠),并且few在同一行上出现两次,只有第一个few更改为asd

The few men, the few women, the brave.


The asd men, the few women, the brave.

这在某些情况下很有用,例如在行首改变特殊字符(例如,替换greater-than符号,有些人用水平制表符引用电子邮件线索中的前一个素材,而在行后面留下引用的代数不等式) ,但在你的例子中,你指定的地方few发生时应该被替换,确保你有那个/g

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

-i选项用于在文件hello.txt上进行编辑。

-e选项指示要运行的表达式/命令,在这种情况下为s/

注意:使用-i -e进行搜索/替换非常重要。如果您执行-ie,则为每个附加了字母’e’的文件创建一个备份。

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/72.html,未经允许,请勿转载。