行区切り文字間の正確な文字セットを変更するには?

行区切り文字間の正確な文字セットを変更するには?

dovecotユーザーデータベースでユーザーパスワードを変更するスクリプトを作成しようとしていますsed

たとえば、次の行を確認してください(これはdovecot userdbの一部です)。

[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa‌​XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa‌​XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::

ユーザーに対してのみ「{SHA512-CRYPT}」で始まる「:」区切り文字の間の文字列を置き換える方法[Eメール保護]「ユーザーには適用されません」[Eメール保護]「sedを使用していますか?

答え1

おそらく:

sed 's/\(\(^\|:\)123@example\.com:\)\([^:]\+\)/\1foo/'

値にエスケープされた区切り文字がないとします。

sed 's/\(\(^\|:\)123@example\.com:\)\([^:]\+\)/\1foo/'    
     |     |         |                |     | |  | |     
     |     |         |                |     | |  | +----- H. End of sub.
     |     |         |                |     | |  +------- G. Sub string
     |     |         |                |     | +---------- F. Match Group 1.
     |     |         |                |     +------------ E. End of Group 3.
     |     |         |                +------------------ D. Group 3.
     |     |         +----------------------------------- C. User
     |     +--------------------------------------------- B. Prefix Group 2.
     +--------------------------------------------------- A. Substitute
  • A: s/代替コマンド。
  • B: (^|:)行または区切り文字の先頭から始まる:グループ 2 は、グループ 1 の一部と一致します。
  • C:マッチング対象ユーザはマッチンググループ1に属する。
  • D: ([^:]+)削除する部分まですべて可能です:。グループ3の一部です。次の区切り記号までのすべてです。おそらくそうすべきかもしれ\(:\|$\)ませんが、それで終わるので:十分です。
  • E: \)グループの削除を終了します。
  • F: \1一致するグループ 1 を再配置します。ユーザー+区切り文字。
  • G: fooすべてが地下室に挿入されます。
  • H: /みんなで終わってください。オプションでグローバル/gですが、一度だけ発生するとします。

答え2

ここから住所を変更できます。

sed '/^[email protected]:{SHA512-CRYPT}/s/{[^:]*/REPLACE/'

ここで、s///代替コマンドは address の関数なので、/regxp/s///が最初に親アドレスと一致しない限り、置換は試行されません。

または単にs///

sed 's/^\([email protected]:\){SHA512-CRYPT}[^:]*/\1REPLACE/'

または、123がコロンの直後に出ていない場合にのみ、行の先頭に固定します。

sed 's/^\(\(.*:\)*[email protected]:\){SHA512-CRYPT}[^:]*/\1REPLACE/'

私は間違いなく複雑なサブ式について見慣れていませんが、この場合はそうする必要はありません。私は通常、アドレス形式を取得できるときに好みます。読みやすく、より効率的で、完全に移植可能だと思います。しかし、一見すると、私は最初はここに固有の複雑さを過大評価したように見えました。

同様に、逆参照と実際の交換を分離できます。たとえば、次のようになります。

sed -e '
/^\([email protected]:\){SHA512-CRYPT}[^:]*/!b
s//\1REPLACE/
#other commands that can be sure to affect only a line matching the 1st address'

上記の例では、address はb一致しない行をスクリプトから削除して一致を確認しますが、行が一致!テストに合格した場合は、次の置換のために変数ビットを格納するデュアルミッションも実行します。さらに、後続のすべてのコマンドは、開始アドレスに一致するラインでのみ実行できます。\1s///

もちろん、中かっこを使用して一致する関数のコンテキストを指定するあまり究極の形式もありません。

sed -e '
/^[email protected]:{SHA512-CRYPT}/{
    s/{[^:]*/REPLACE/
    #other function commands
};/other match function/{
    #still more commands...
}'

答え3

使用awk:

awk -F':' '/^[email protected]/ {$2="NEWPASSWORDHERE"}1' OFS=':' infile

[email protected]:NEWPASSWORDHERE:::
[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa‌​XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
  • awkこのオプションを使用してコロン()をフィールド区切り文字に-F設定し、行が始まると()列2を新しい値()に置き換えます。:^[email protected]$2NEWPASSWODHERE

  • OFS=':'出力フィールド区切り文字を空白(デフォルト)からコロン(:)に変更します。

  • 最後に、1印刷はデフォルトで有効になります。

関連情報