web-dev-qa-db-ja.com

キーと値のペアのカット

cutを使用してCSVファイルの指定された列を切り取る方法と同様に、テキストからキーと値のペア(キーが一意で指定されている)を切り取る簡単な方法を探しています。私が探しているキーは、常に行内の同じ相対位置にあるとは限りません。つまり、cutの後にsedを続けても、うまくいきません。 mの検索は、常に同じ,区切りの列にあるとは限りません。

問題のテキストは確かにCSVですが、値が=で区切られたキーと値のペアである場合があります。

たとえば、次の3行でファイルを解析するとします。

Foo=1, Bar=2, Baz=3
Bar=4, Foo=2, Baz=3
Bar=42, Baz=42, Foo=3

そして、私はこのテキストをカットして、特定のキーのキー/値ペアを生成したいと思います。 Fooを探していた場合、希望する出力は次のようになります。

Foo=1
Foo=2
Foo=3

理想的には、cutと同様の構文を持ち、stdinとファイルの両方から読み取ることができるコマンドラインツールが欲しいです。

そのようなツールはありますか?

7
John Dibling

grep-oオプションでこれを行うことができます:

grep -o 'Foo=[^,]*' file
10
jimmij

選択肢のリストを切り上げるawkソリューション:

awk -v RS=', ' -F'=' '$1=="Foo"' <file>

各レコードを', 'で区切るように扱い、各レコードを=文字のフィールドに分割します(-Fを使用)。次に、最初のフィールド$1を照合するだけです。ここに示す提案は、単純な文字列マッチングです。正規表現を自由に使用してください。 $1~/\<Foo\>/

3
h.j.k.

実際の状況の複雑さに応じて、次のsedコマンドで十分な場合があります。

sed -n 's/^.*\(\<Foo=[^,]*\).*/\1/p'

これが実際の例です

FIELD='Foo'
sed -n "s/^.*\(\<${FIELD}=[^,]*\).*/\1/p' << xxEOFxx
Foo=1, Bar=2, Baz=3
Bar=4, Foo=2, Baz=3
Bar=42, Baz=42, Foo=3
xxEOFxx
Foo=1
Foo=2
Foo=3
2
roaima

あなたの例を考えると、もろい解決策はcutを含むことができます:

tr ', ' '[\n*]' <input | cut -sd F -f1-

...各キー/値のペアを別々の行に配置し、間にあるカンマとスペースをtransで\newlinesに変換し、次に、含まない行をcuttingアウトします。 F。しかし、これは非常に特殊な例であり、Fが必要なキーと値のペアでのみ発生することが確実な場合にのみ機能します。

それ以外の場合、sedは私が使用するものです。

sed 'y/ ,/\n\n/;/^Foo=/P;D' <input

これはまた、介在するカンマとスペースを\newlinesにtransformしますが、Printは、文字列Foo=で始まるキー/値のペアのみを_intします。スペースが信頼できるセパレーターである限り、上記はFooキー/値のペアを可搬性のある方法でそれぞれ別の行に出力し、入力行で何回発生しても他に何も出力しません。 -印刷したいキー/値が含まれていない行でも。

2
mikeserv

_ [で使用できるgrepがない場合、-oオプション、これはトリックも行うべきです:

sed -e 's/, /\n/g' | grep '^Foo='

これは、sedを使用して、すべてのコンマ+スペースを改行で置き換え(各キーと値のペアを独自の行に分割)、次にgrepを使用して「Foo」キーのみを検索します。

テストケース:

printf "%s\n" "Foo=1, Bar=2, Baz=3" "Bar=4, Foo=2, Baz=3" "Bar=42, Baz=42, Foo=3" \
    | sed -e 's/, /\n/g' | grep '^Foo='
1
godlygeek