プロセスに変換したい 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.name1
、user.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 つの方法は次のようになります。tr
tr
cat input_file | tr "\012" "%" | sed "s/%/; /g"
(改行は によって % に変換されtr
、sed
すべての % 文字が "; " 文字ペアに変換されます。)
答え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