web-dev-qa-db-ja.com

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

5
3therk1ll

複数の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"
}
_
18
Attie

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()))'
3
Bob

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
0
Paulo

これらの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はすべての%文字を ";"文字ペアに変換します。)

0
J. Hansen