コマンドを使用してファイル内のテキストを検索および置換する


回答:


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

説明:

  • sed = Stream EDitor
  • -i =インプレース(つまり、元のファイルに保存する)
  • コマンド文字列:

    • s =代替コマンド
    • original =置換する単語(または単語自体)を記述する正規表現
    • new =置換するテキスト
    • g = global(つまり、最初の出現だけでなくすべてを置換)
  • 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.txtsed -i '' 's/original/new/g' file.txt、長さゼロの拡張子を使用して実行することもできますが、バックアップは生成されません。
カーク

19
MacOSのユーザは、-iのパラメータとして-i後に「「」を追加する必要がありますed.gs/2016/01/26/os-x-sed-invalid-command-codeファイルが上書きされますように。
geoyws

32

これを行うには、さまざまな方法があります。1つは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
フェドルキ

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使われるのか興味があるなら、それは基本的に行ごとにファイルを読むシェルの方法です。参照用にこれを参照してください。

AWK

テキスト処理ユーティリティであるAWKは、このようなタスクに非常に適しています。正規表現に基づいて、単純な置換とより高度な置換を実行できます。2つの機能を提供します:sub()gsub()。最初のものは最初の出現のみを置換し、2番目は文字列全体の出現を置換します。たとえば、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

このツールの良いところは、その場で編集できること-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スクリプトを実行する正確なコマンドは次のようになります

 $ ./myscript.py input.txt

または

$ python ./myscript.py input.txt

もちろん、それ./myscript.pyが現在の作業ディレクトリにあることを確認し、最初の方法では、それが実行可能に設定されていることを確認してくださいchmod +x ./myscript.py

Pythonには正規表現を含めることもできreます。特に、re.sub()より高度な置換に使用できる機能を持つモジュールがあります。


1
すてきなコンパイル!ここで言及されていない別の可能な方法は、使用しているtrUNIXでのコマンド
Tapajitデイ

1
@TapajitDeyはい、tr もう一つの素晴らしいツールですが、それは例えば(文字のセットを交換するためのものであることに注意してくださいtr abc cde翻訳するでしょうacbdそれはのように単語全体を交換するとは少し異なっている。sedまたはpython
Sergiy 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が配置された列に関係なく、すべての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

(ドッカーコンテナに)アルパインLinux上でテストされ、何も出力を持っていない
SalathielGenèse

@SalathielGenèse何を達成しようとしていますか?
アビナッシュラジ

私はenvのinotifywait下でファイルを見てsh、CSV形式でデータを報告しています(カスタム形式にはバグがあるため)。次に、シェルスクリプトでCSVドキュメントを処理する簡単な方法はないと考えました。そこで、CSVを解析して報告するための非常に簡単なスクリプトを開始しました。CSVの仕様を読んで、予想よりも精巧で、二重引用符で囲まれた複数行の値をサポートしていることに気付きました。私はsedトークン化に頼っていましたが、sedマルチラインと呼ばれるものでさえ最大2行であることにすぐに気付きました。CSV値の1つが3行以上にわたる場合はどうなりますか?
サラティエルジェネーズ

あなたの問題を質問として尋ねる方が良い。
アビナッシュラジ

8

sedあるS tream itor、あなたが使用できるように|送信する(パイプ)を標準ストリームを通じて(STDINとSTDOUT、具体的に)sed、それUnixの哲学の伝統で便利なツール作り、その場でプログラム的にそれらを改変すること。-i下記のパラメーターを使用して、ファイルを直接編集することもできます。
以下を考慮してください

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

s/は、見つかった式を次のように置き換えるために使用されます。fewasd

少数の、勇敢な。


asd、勇敢。

/gこれは「グローバル」の略で、行全体でこれを行うことを意味します。あなたがオフのままにしておくと/g(とs/few/asd/、そこには常にどんな3つのスラッシュがないように必要)とfew同じ行に2回出現し、最初はfewに変更されますasd

少数の男性、少数の女性、勇敢な人。


asdの男性、少数の女性、勇敢な人。

これは、行の先頭にある特殊文字を変更するなど、状況によって便利です(たとえば、電子メールスレッドで以前の素材を引用するために使用する大なり記号を水平タブに置き換え、引用された代数の不等式を行の後半に残すなど)ただし、どこでも few発生するように指定する例では、置換する必要があります/g

次の2つのオプション(フラグ)は1つに結合されます-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()]にすべて置換するには、次のようにします。

ex1:

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

ex2:

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

[tensorboard / program.py]は検索するファイルです


こんにちは。文字列の選択(logdir', ''-> /logdir', os.getcwd())により、この回答の解析が難しくなります。また、sed onを使用するファイルは、質問の一部ではないため、最初に答えを見つけることを指定する価値があります。
mwfearnley

こんにちは、この答えは検索であり、ファイルで<old text>が見つかった場合はすべて置き換えます。
グエントゥ

私は彼らがkersでテンソルボードを使用しているすべての人にこの答えを選択します。彼らはログフォルダーに滞在するときにコマンドを変更する必要があります:tensorboard --logdir = '/ path / to / log / folder /' to use:tensorboard only。それは非常に便利です
グエン・トゥアン・アイン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.