Bashでの文字列の違い


110

スクリプト内の2つの文字列の違いを判別する方法を見つけようとしています。これはdiffやcommで簡単に実行できますが、ファイルを扱っていないため、ファイルに出力したり、比較したり、読み直したりしたくありません。

comm、diff、cmpはすべて、2つのファイルまたはファイルと標準入力のいずれかを渡すことができることがわかります。2つのファイルを出力したくない場合は、これで十分でしょう。

私はgrepまたは正規表現を使用できると考えて掘り下げていましたが、私はそうは思いません。


1
実際にやりたいことは何ですか?

部分文字列操作と組み込みテスト操作をIFSの変更と共に使用して比較できますが、文字ごと、単語
ごと

回答:


198

使用するdiffか、comまたはあなたが好き:

diff  <(echo "$string1" ) <(echo "$string2")

Greg's Bash FAQ:Process Substitution

または名前付きパイプで

mkfifo ./p
diff - p <<< "$string1" & echo "$string2" > p

Greg's Bash FAQ:名前付きパイプの操作

名前付きパイプはFIFOとも呼ばれます。

-自分自身では、標準入力のためです。

<<< 「ここの文字列」です。

&のようなものです;が、それをバックグラウンドに置きます


5
正解は+1。+1は、記号の説明を示します。さらに、GregのBash FAQは次の場所に移動しました:mywiki.wooledge.org上記のページへのリンクは現在、mywiki.wooledge.org / ProcessSubstitution
timemachine3030

どうも!また、これは動的ファイル記述子を示しますFUNC(){ echo "$@"; "$@"; }; FUNC diff <(echo a) <(echo b);
Aquarius Power

2つのシャスムを比較するためにそれを探していました。それを行うためのよりエレガントな方法があるかどうかはわかりませんが、動作します。
fuma

これは、$ string1と$ string2に複数の行がある場合に機能するようで、diffは加算または減算された行を出力します。文字列が単一の行で、行であり、2つの文字列の間に違いがある場合はどうなりますか?
alpha_989 2017

@ alpha_989、ここにあなたの答えがあります:$ diff <(echo "Here are the letters in String One.") <(echo "Here are the characters in String Two.") \n 1c1 \n < Here are the letters in String One. \n --- \n > Here are the characters in String Two. \nパイプの使用は似ていますが、プロセス番号が表示さ1c1れ、次のから始まり、$<kbd> Enter <kbd>を押すまで待機します(または他のコマンドを実行できます...)
bballdave025

19

この質問を思い出します:Bashで2つのパイプラインをどのように比較できますか?

あなたがbashセッションにいるなら、あなたは次のことをすることができます:

diff <cmd1 <cmd2
diff <(foo | bar) <(baz | quux)

<bashで管理される- -彼らは作成され、一時ファイルとは異なり、自動的に破棄されるように、匿名の名前付きパイプを作成します。

したがって、2つの異なる文字列をコマンドの一部として分離できた場合(grep、awk、sedなど)、次のようなことができます。

diff < grep string1 myFile < grep string2 myFile

(あなたが思うならば、あなたは次のようにあなたのファイルの行を持っているstring1=very_complicated_valuestring2=another_long_and_complicated_value':あなたのファイルの内部フォーマットを知らなくても、私は正確なコマンドをお勧めすることはできません)


13

cmpはbashのProcess Substitution機能を好みます:

$ cmp -bl <(echo -n abcda) <(echo -n aqcde)
  2 142 b    161 q
  5 141 a    145 e

位置2について言うと、最初はabが発生し、2番目はaqが発生します。ポジション5では、別の違いが生じています。これらの文字列を変数に置き換えるだけで、完了です。


これは、文字列が同じ長さの場合にのみ機能します。
strpeter 2016年

11

3つの弦があるとします

a="this is a line"
b="this is"
c="a line"

aからプレフィックスbを削除するには

echo ${a#"$b"}  # a line

aからサフィックスcを削除するには

echo ${a%"$c"}  # this is

2
これはbashのやり方だと思います。それはうまくいきました。ただし、その構文を理解するのは少し難しいです。
Mikael Roos、2014年

@MikaelRoos同意する。(とにかく私にとって)読みやすいのはsedを使用することですecho "$a" | sed "s!^$b!!g" (処理する変数がパスの場合は、標準のsedセパレーター/ for!を取り替えました。また、echo:の代わりにhere文字列を使用できますsed ... <<< $a。)
ACK_stoverflow

0

もう一つの例:

before="184613 102050 83756 63054"
after="184613 102050 84192 83756 63054"

comm -23 <(tr ' ' $'\n' <<< $after | sort) <(tr ' ' $'\n' <<< $before | sort)

アウトプット

84192

ここで元の答え

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.