Bash での複数の sed コマンド

Bash での複数の sed コマンド

プロセスに変換したい JSON 形式のユーザー名とパスワードのファイルがあります。

これまでさまざまなコマンドを使用して処理してきましたsedが、今後は 3 つのコマンドすべてを 1 つにまとめる方法を知りたいです。

オリジナルフォーマット

    { "user.name1" : "hashed_password",
"user.name2" : "hashed_password" }

望ましい出力

user.name:hashed_password

これらは私が実行したコマンドですが、パイプを使用しても、単に連結しても、エラーが発生するため、それらを連結することができませんでしたsed: -e expression #1, char 8: unknown option to 's'

違反コマンド...

sed -i 's/\"//g/s/\,/\n/g/\s//g' input_file 
sed: -e expression #1, char 8: unknown option to `s'

以下のコマンドを 1 つに連結するにはどうすればよいでしょうか?

コマンド 二重引用符を削除する

sed -i 's/\"//g' input_file

カンマを改行に置き換える

sed -i 's/\,/\n/g' input_file

空白を削除する

sed -i 's/\s//g input_file

答え1

複数のsedコマンドを1つの「脚本" では、複数の-eフラグを使用できます (移植可能です):

sed -i -e 's/\"//g' -e 's/\,/\n/g' -e 's/\s//g' input_file

または、セミコロン区切り文字(すべての実装で使用できるわけではありません):

sed -i 's/\"//g;s/\,/\n/g;s/\s//g' input_file

中括弧の処理も追加する必要があります - {}...


そうは言っても、JSONを適切に解析して処理するには、実際には使用すべきではありませんsed...おそらく試してみてくださいjq

jq -r 'keys[] as $k | "\($k):\(.[$k])"' input_file

出力:

user.name1:hashed_password
user.name2:hashed_password
  • keys[] as $k各キーを反復処理してその値を格納します$k
    • 例: user.name1user.name2
  • "\($k):\(.[$k])"$kを代入して文字列を形成します。.[$k]
  • を使用すると-r、出力文字列から引用符が削除されます(モード)

JSON を処理するために を使用するとsed、さまざまな問題が発生します...たとえば、次の (完全に有効な JSON) 入力をどのように処理しますか?

{
    "user.name1" :
        "hashed_password",
    "user.name2" :
        "hashed_password"
}

答え2

JSON のような標準化された入力を扱う場合、通常は正規表現ではなく適切なパーサーを使用する方がよいでしょう。たとえば、エスケープ シーケンスを正しく変換できます (ただし、特定の入力データではそれができない場合もあります)。

残念ながら、coreutils 内に JSON を処理するための優れたツールはありません。アティーズ提供 jqパッケージを自由にインストールできる場合、適切なオプションです。

追加のパッケージをインストールできない場合でも、Python では特に難しいことではありません。次のスクリプトを例に挙げます。

import json,sys
for (k, v) in json.load(sys.stdin):
    print(k + ":" + v)

これは 1 行に圧縮できます。

cat inputdata | python -c 'import json,sys;print("\n".join((k + ":" + v) for (k, v) in json.load(sys.stdin).items()))'

答え3

これらのコマンドで実行している単純な文字削除には、sed代わりに を使用することをお勧めします。trの唯一の目的は、改行を含む個々の文字を削除、圧縮、または置換することです (は正規表現に基づいており、通常はバッファ区切りとして改行に依存するため、 sed を使用して改行を変更するのは難しいです)。 このコマンドは、必要なことすべてを実行するとsed思います。tr

cat json_filename | tr -d "{}\" \012\011\015" | tr "," "\012"

最初のtrコマンドは、中括弧、二重引用符、スペース、復帰 (8 進数 012、ASCII 10)、タブ (8 進数 011、ASCII 9)、および改行 (8 進数 015、ASCII 13) 文字をすべて削除します。2 番目のtrコマンドは、すべてのカンマを復帰に置き換えます。JSON ファイルの変数名と値にカンマが含まれていない限り、これらのコマンドを使用すると、専用の JSON パーサーが不要になります。

とはいえ、それぞれが独立して動作するコマンドのセットがある場合sed、それらを結合するには、ファイルから個別のコマンドを読み込む「-f」オプションを使用するのが最も簡単ですsed。各文字列を 1 行に 1 つずつ記述した s/.../.../g 文字列をファイルに記述し、「-f」オプションの後にそのファイル名を指定します。たとえば、sedリストした 3 つのコマンドで十分な場合は、次の内容だけを記述した「json.convert.sed」というファイルに記述できます。

s/\"//g 
s/\,/\n/g
s/\s//g

sed次に、次のコマンドを使用してこのコマンド ファイルを呼び出します。

sed -f json.convert.sed

とはいえ、これらのsedコマンドは、あなたが望むことを実現するのに私には役立ちませんし、sed改行文字を変更できるかどうかもわかりません。これは、sedが古い「ed」行エディタ (「スクリプト」可能なバージョン) に基づいているためです。このエディタは、一度に 1 行ずつ編集するように設計されているため、入力の各行は改行を区切り文字として使用して「解析」され、次に行 (改行なし) が編集エンジンに渡され、編集コマンドが適用され、編集された行が改行付きで出力されます。その後、ループが繰り返されます。 を使ってsed改行を変更できたのは、まず を使って改行を (入力には表示されない) 特定の文字に変更することでした。 がそれを実行するので、改行を削除するだけであれば、この方法trを使用する意味はありません。ただし、たとえば、改行を末尾にスペースがあるセミコロンに変換したい場合、その 1 つの方法は次のようになります。trtr

cat input_file | tr "\012" "%" | sed "s/%/; /g"

(改行は によって % に変換されtrsedすべての % 文字が "; " 文字ペアに変換されます。)

答え4

次のように組み合わせることもできます:

sed -i 's/\"//g;s/\,/\n/g;s/\s//g' input_file

の削除を追加するのを忘れました{}。したがって、おそらく次の操作が必要になります。

sed -i 's/\"//g;s/\,/\n/g;s/\s//g;s/{//g;s/}//g' input_file

関連情報