sedで4回交換

sedで4回交換

この文字列の2番目、3番目、4番目、5番目の点を変更したいと思います。

2019-03-17T11:32:28.143343Z;1234.5678;901.234;567.89012;3456.78;192.168.0.1

カンマを使用すると、次のような結果が得られます。

2019-03-17T11:32:28.143343Z;1234,5678;901,234;567,89012;3456,78;192.168.0.1

最初のカンマと6番目のカンマ(およびそれ以降のすべてのカンマ)は変更されていないままにしてください。

私は何度も実行できる次のコマンドを見つけました(しかしベストプラクティスではないかもしれません)。

echo "$tmp" | sed 's/\./\,/2'

1つのコマンドでこれをどのように実行できますか?

答え1

データは;6つの区切りフィールドで構成されており、フィールド2〜5(1または6ではない)の点をカンマで置き換えようとします。

これは最も簡単な方法ですawk

awk -F ';' 'BEGIN { OFS=FS } { for (i=2; i<=5; ++i) gsub("\\.", ",", $i); print }' file

与えられたサンプルデータに基づいて、次のようになります。

2019-03-17T11:32:28.143343Z;1234,5678;901,234;567,89012;3456,78;192.168.0.1

コードは単に;各入力行の - で区切られたフィールドを繰り返し、ループが繰り返す個々のフィールドに対してグローバル検索と置換を呼び出します(またはでgsub()実行するように)。s/\./,/gy/./,/sed

次に、修正された行を印刷します。

この-Fオプションは入力フィールド区切り文字をセミコロンに設定し、そのBEGINブロックを使用して出力フィールド区切り文字も同じ値に設定します(そうでない場合はスペースで区切られたフィールドが表示されます)。


を使用すると、sed次のことができます。

sed 's/\./,/2; s/\./,/2; s/\./,/2; s/\./,/2' file

つまり、2番目の点を4回交換します。 2番目の点は交換するたびに置き換えられます。ただし、これは各フィールド内の値の数が固定されていると仮定します。

この問題を解決するには、フィールドに複数のドットで区切られたコンテンツがある場合は、次のようにします。

sed 'h; s/^[^;]*;//; s/;[^;]*$//; y/./,/; G;H;x; s/;[^\n]*\n/;/; s/\n.*;/;/' file

簡単に言えば、このコマンドが実行する作業は次のとおりです。

  1. 元の行を予約済みスペースにコピーします。
  2. パターン空間から最初と最後のフィールドを削除します。
  3. パターン空間のすべての点をコンマに変更します(コマンドですy)。これで、コンマに変更する必要があるすべての点が変更されました。これで、パターンスペースの中間ビットとスペアスペースの元のデータから行を再組み立てする必要があります。
  4. G;H;xパターン空間に以下を含めるように(AND)

    1. 生の文字列の後に改行文字が続きます。
    2. 修正された中間数字の後に改行文字が続きます。
    3. 元の文字列です。
  5. これで、パターン空間には以下が含まれます。3行。最初の行の最初のフィールドと改行文字を除くすべての項目を削除し、削除されたビットを;

  6. 最後の行と同様の操作を行います。つまり、(現在の一意の)改行文字と最後の行の前のすべての項目を削除して;に置き換えます;

  7. 完璧。

または、単にawkコードを使用することができます。

答え2

;他の答えは質問に明記されていない入力について仮定しているので、正確に6点)、私はその仕事をする少し不器用な答えを提供します。

sed 's/^\([^.]*\.[^.]*\)\.\([^.]*\)\.\([^.]*\)\.\([^.]*\)\./\1,\2,\3,\4,/'

これにより、各入力行が次のように分類されます。

  • グループ1キャプチャ:行の先頭から始め、除外 .、その後 .(行の最初)の後にランダムな長い文字シーケンスが続きます。ただし、 .
  • .(行から2番目)、
  • キャプチャグループ2:除外 .
  • .(行から3番目)、
  • グループ3キャプチャ:除外 .
  • .(行から4番目)、
  • グループ4キャプチャ:除外 .
  • .(行の5番目)、
  • 次の内容(正規表現と一致しないが正規表現がで終わらないため、行が上記より多い可能性があります  $)。

そしてそれに置き換え

  • グループ1キャプチャ:2回目まですべて .この行(最初の行を含む)では、
  • ,(2回目を交換.)、
  • グループ2キャプチャ:2番目のグループ間のすべて .第三に、
  • ,(3番目の交換.)、
  • グループ3キャプチャ:3番目のグループ間のすべて .第四、
  • ,(4番目を交換.)、
  • グループ4キャプチャ:4番目のグループ間のすべて .第五、
  • ,(第五交換.)、
  • 5回目以降の内容 .

したがって、2番目、3番目、4番目、5番目の点をコンマに置き換えます。

  • ポイントが5個未満の行は変更されません。
  • これにより、5番目のポイント以降のポイント数は変わらず、そのまま残ります。
  • 行に5つの点しかない場合(つまり、6番目の点はありません)、2番目、3番目、4番目、5番目の点が置き換えられます。

GNU sedのもう一つの方法は次のとおりです。

sed 's/\./\n/6g; s/\./,/2g; s/\n/./g'
  • s/\./\n/6g6番目の点から始まるすべての点を改行文字に置き換えます。
  • s/\./,/2g  カンマで始まるすべての点を2番目の点に置き換えます。ただし、最初のコマンドは5番目(存在する場合)以降のすべてのポイントを削除するため、実際には2番目から5番目までのみです。
  • s/\n/./g すべての改行を再点に変更します。もちろん、行にある唯一の改行文字は元の点だった文字なので、元の点に戻ります。

したがって、線に3つの点しかない場合、2番目と3番目の点が変わります(4番目と5番目の点が存在しなくても)。

警告する: コマンドのフラグとして数字と a の組み合わせの動作は次g のとおりです。sPOSIX が指定されていません。 そして実装によって異なる場合があります。ドキュメントに記載されているように、GNU SEDが機能する方法です。GNU SEDマニュアル

答え3

ループを持つもう一つのsed:

sed ':A;s/\([^.]*\.[^.]*\)\.\(.*;[^;]*$\)/\1,\2/;tA' infile

答え4

sedエディタを使用して、次のようにこの問題を解決できます。

$ sed -e '
    y/./\n/
    s/\n\(.*\)\n/.\1./
    y/\n/,/
' input.txt

前提は、パターン空間に文字が存在しないように、まずすべての点を改行文字に変換することです。次に、最後と最初の改行を再点に変更します。残りの改行はすべてコンマに変換されます。

HTH。

関連情報