GNU Sedでは、最初のものを1)に、2番目のものを2)に置き換えます。

GNU Sedでは、最初のものを1)に、2番目のものを2)に置き換えます。

擬似コードは次の連続です。この回答

gsed 's/|/1)/g' 's/|/2)/2g' 's/|/3)/3g' 's/|/5)/4g' 's/|/5)/5g' 
<input.csv >output.csv

もちろんこれはうまくいきません。私が興味を持っているのは、gsedそのようなサイクルをどのように管理するかです。

gsedそのようなループに拡張する方法は何ですか?

答え1

上記の場合は、次のようにできます。

gsed 's/|/1)/; s/|/2)/; s/|/3)/; s/|/4)/; s/|/5)/'

例:

$ echo '| | | | |' | sed 's/|/1)/; s/|/2)/; s/|/3)/; s/|/4)/; s/|/5)/'
1) 2) 3) 4) 5)

|この方法は、行の最大数を事前に推定してs/|/N)/それに応じて追加できる場合に有効です。

1行の最大数を予測できない場合でも、を使用して計算でき、|バッファgsedを保持するカウンタを使用して次を使用できます。この賢いデバイス著者:ブルーノハイブル。しかし、実際の実装は少し難しいので、そのままにします。マゾヒスト敏感な読者。

もちろん、最も簡単な方法は以下を使用することですawk

awk '{ cnt = 0; while(sub(/\|/, ++cnt ")")); print }'

証明する:

$ echo '| | | | |' | awk '{ cnt = 0; while(sub(/\|/, ++cnt ")")); print }'
1) 2) 3) 4) 5)

答え2

もう一つのsed:

sed -n '1x;1s/^/12345/;1x;G;:t
        s/|\(.*\n)\(.\)/\2)\1/;tt
P'    <infile >outfile

awkしかし、ここがより適切かもしれません。

より複雑なソリューション:

他の質問の結果を考えると...

Question ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n
Que|stion ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n

...そしてそれを渡します...

sed '   s/^/!/;/|/s/\(.*;\)*[^|]*/&\
|/g;    s/.*\(\n\).*/::::::\1&\1::/' |
nl  -d:: -hp^\) -s\)\              |
sed -e' /./{ s/^ *!//;P;d;:n' -e'};N;/\n$/!bn
        s/[0-9 ]*\n *\([^;|)]*) |*\)|/ (\1/g;D'

...得るために...

Question ipsun; option (1) | option (2) | option (3) | option (4) | ... (5) | option n (6)
Que|stion ipsun; option (1) | option (2) | option (3) | option (4) | ... (5) | option n (6)

崩れると思います...

sed '   s/^/!/;/|/s/\(.*;\)*[^|]*/&\
)/g;    s/.*\(\n\).*/::::::\1&\1::/' |..

...最初のステップです。出力準備が完了しましたnl

nl標準ユーティリティの中で独自の機能を持っています。(ほとんどは入力ストリーム全体を1つの凝集力のある単位として扱います)- できますから論理的に入力ファイルを区切って部分nl入力を次のように分割します。ヘッダー歩行者それぞれ論理ページそれは。ページの 3 つのセクションごとに、ユーザーは異なる番号を指定できます。スタイルそれぞれについて、そしてそれぞれについて論理ページユーザーは新しい行を受け取ることができます計算

上記のようにsedしました。

  • s/^/!/
    • それ以外の場合は、sのセクション区切り文字が誤って入力に表示されるのを防ぐことができますが、処理の反対側でnl切り取る先行スペースのマーカーとしても機能します。nl
  • /|/s...
    • これは、少なくとも1つのパイプと明示的に一致する行にのみ置換を適用しようとします|
  • ...s/\(.*;\)*[^|]*/&\n|/g
    • これは、一致する可能性のあるパターンにグローバル置換を適用します。(または何も)パイプなのに、時には後ろにセミコロンが |ない場合もあります。;
      • 0回以上\(.*;\)*一致するため、ほとんどの場合は空の文字列と一致します。*ただし、マッチングが1つ以上のセミコロンを含む行にサブ式を最初に適用すると、行の先頭;から最後のセミコロンまで、全体のパターン空間範囲が効果的にスキップされます。
      • これの目的は、[^|]*発生する部分文字列との一致を防ぐことです。今後セミコロンで区切るのでスキップします。質問完全な文字列の一部です。
    • このパターンが現れるたびに、そのパターンはそれ&自体で置き換えられ、追加のパターンが追加されます。\n|
  • s/.*\(\n\).*/::::::\1&\1::/
    • これは \n、少なくとも1つのewlineを6つのコロンで含むすべてのパターンスペースを置き換え、次に私たちがキャプチャしたewline、それから私たちがキャプチャした\1\newline &\1\nそして2つのコロンで置き換えます。
    • 文字列を使用します::nl次のようにセクション-d区切り記号。これらの文字列の1つは次から始まります。nl 歩行者3つの文字列が1を表示するセクションヘッダー- そして新しい論理ページ。
    • nl〜するただ区切り文字は、1行に単独で表示されると認識されます。

...この時点のデータフローは次のとおりです。

:::::
!オプション1に尋ねてください。
||オプション2
||オプション3
||オプション4
||
||オプションn
|
::
:::::
!質問|ipsun;オプション1
||オプション2
||オプション3
||オプション4
||
||オプションn
|
::

...もう通過できます...

...|nl -d:: -hp^\) -s\)\ |...
  • -d::
    • これは以下を指定します。::区切り文字列。
    • nl-d入力の各区切り文字文字列を出力の空白行に置き換えます。
      • nl出力行の先頭に数字を挿入するか、数値文字列の長さに一致するように番号付けされていない行の先頭にスペースを挿入します。
      • したがって、出力の唯一の空行は、区切り文字列であった行です。
  • -hp^\|
    • これは-hリーダースタイルの意味正規表現パターンに一致するすべての行に番号を付けます。
    • nlになるヘッダー次の項目のみを含む行間に発生する各行シーケンスの状態::::::もう一つは::
    • 基本nl番号ただ体の部分には番号が付けられていません。ヘッダーまたは歩行者別言します。
  • -s\)\
    • nlこれは、番号付きの各行のヘッダーとその前に挿入された番号の間に挿入される区切り文字列です。

...この時点のデータフローは次のとおりです。

        !オプション1に尋ねてください。
     1)||オプション2
     2)||オプション3
     3)||オプション4
     4) ||
     5)||オプションn
     6)|


        !質問|ipsun;オプション1
     1)||オプション2
     2)||オプション3
     3)||オプション4
     4) ||
     5)||オプションn
     6)|

...最終的にこの問題を処理する方法は次のとおりです。

sed -e' /./{s/^ *!//;P;d;:n' -e '};N;/\n$/!bn
        s/[0-9 ]*\n *\([^;|)]*) |*\)|/ (\1/g;D'
  • /./{...
    • これは、1つ以上の文字を含むすべての行で一致中心機能を開始します。
    • その後には複数のコマンドを含めることができますが、関数の親アドレスと最初に一致するパターンスペースにのみ適用されます。
  • ...{s/^ *!//
    • nlここでは、一致する行の頭部に挿入されたすべてのスペースと挿入された前髪を切り取ります。
  • P;d;:n
    • これはパターンスペースの最初の行Pに印刷されます。\n
    • その後、dパターン空間を削除します。
    • 次に分岐ラベルを定義します:n
    • これからは、空行で始まる一連の行だけを処理します。
  • N
    • Nこれは拡張入力ラインを取得し、\newline 文字の後のパターン空間に追加します。
  • /\n$/!bn
    • $パターン空間がewlineで終わらなくても(\next行が空の場合はそうです)、私たちは常にラベルスタック入力に戻ります。Nb:n
  • s/[0-9 ]*\n *\([^;|)]*) |*\)|/ (\1/g'
    • g部分交換です。
    • すべてのシーケンスを置き換えます。
      • *0個以上の[0-9 ]文字
      • 以下は\newlineです
      • その後に*0個以上が続きます。<スペース>
      • その後に*ゼロ個以上の^コロンやパイプではない文字が続きます。
      • )括弧の後に
      • 後ろに|パイプが来る可能性があります
      • |その後はパイプが続きます。
      • ^コロン/パイプ以外の文字、閉じ括弧、およびパイプのみが含まれています。
  • D
    • 次に、パターン空間の最初の行をD削除します。\n(シーケンスが空行で始まるので、これは最初の文字です)残りの部分をスクリプトの上部に送り、新しいサイクルPでスペースと爆発をトリミングして印刷します。

最終結果は次のとおりです。

Question ipsun; option (1) | option (2) | option (3) | option (4) | ... (5) | option n (6)
Que|stion ipsun; option (1) | option (2) | option (3) | option (4) | ... (5) | option n (6)

関連情報