プロセスに変換する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
複数のsed
コマンドを1つの "script"に入れるには、複数の_-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
_を使用すると、出力文字列から引用符が削除されます(rawモード)sed
を使用してJSONを処理すると、あらゆる種類の問題が発生します...たとえば、次の(完全に有効なJSON)入力をどのように処理しますか?
_{
"user.name1" :
"hashed_password",
"user.name2" :
"hashed_password"
}
_
JSONのような標準化された入力を扱う場合、通常は正規表現よりも適切なパーサーを使用する方が適切です。たとえば、エスケープシーケンスを正しく変換します(ただし、特定の入力データでは変換できない場合があります!)。
残念ながら、coreutils内でJSONを処理するための優れたツールはありません。 Attieが提供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()))'
Sedは複数行の編集を処理できますが、私はAttieとBobに同意します。sed正規表現を使用したjsonの解析は悪夢になる可能性があります。
sed -nr '/\{/ b Load ; d
: Load
/\}/ b Edit ; N ; b Load
: Edit ; s/[^"]+"([^"]+)"[^"]+"([^"]+)"(.*)/\1:\2\n\3/ ; t Print ; d
: Print ; P ; s/[^\n]+\n// ; t Edit' <<'eof'
{
"user.name1" :
"hashed_password1",
"user.name2" :
"hashed_password2"
}
{ "user.name3" : "hashed_password3",
"user.name4" : "hashed_password4" }
{ "user.name5":"hashed_password5"}
eof
user.name1:hashed_password1
user.name2:hashed_password2
user.name3:hashed_password3
user.name4:hashed_password4
user.name5:hashed_password5
これらの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
オプションを使用してファイルから個別のコマンドを読み取るのが最も簡単です。 s /.../.../ g文字列をファイルに入れ、各文字列を1行に記述し、 "-f"オプションの後にそのファイル名を指定します。たとえば、リストした3つのsed
コマンドで問題がなければ、これらを単に「json.convert.sed」という名前のファイルに入れ、次のように記述します。
s/\"//g
s/\,/\n/g
s/\s//g
次に、次のコマンドを使用して、このコマンドファイルでsed
を呼び出します。
sed -f json.convert.sed
そうは言っても、これらのsed
コマンドは私があなたが望むことを達成するのに機能しません、そしてあなたがsed
を取得して改行文字を変更することができるかどうかはわかりません。これは、sed
が一度に1行ずつ編集できるように設計された古い「ed」行エディター(「スクリプト」対応バージョン)に基づいているため、入力の各行は区切り文字として改行、次に改行なしの行が編集エンジンに渡され、編集コマンドが適用され、編集された行が改行付きで出力されます。その後、ループが繰り返されます。 sed
を使用して改行を変更するには、最初にtr
を使用して改行を別の文字(入力に表示されないもの)に変更するしかありませんでした。 tr
が自動的に行うので、改行を削除するだけの場合は、この方法でtr
を使用しても意味がありません。しかし、たとえば、改行を末尾にスペースのあるセミコロンに変換したい場合、それを行う1つの方法は次のとおりです。
cat input_file | tr "\012" "%" | sed "s/%/; /g"
(改行はtr
によって%に変換され、次にsed
はすべての%文字を ";"文字ペアに変換します。)