同様の作業を行うにはsedを使用する必要がありますか?
qq ab xyz ab qq aa ab
になる:
qq ab xyz +ab+ +qq+ aa +ab+
答え1
入力に<
、>
または+
文字がすべて含まれていない場合は、次のことができます。
sed '
s/[[:alnum:]]\{1,\}/<&>/g;:1
s/\(<\([^>]*\)>.*\)<\2>/\1+\2+/;t1
s/[<>]//g'
次の場合、いつでもこの問題を回避できます。
sed '
s/:/::/g;s/</:{/g;s/>/:}/g
s/[[:alnum:]]\{1,\}/<&>/g;:1
s/\(<\([^>]*\)>.*\)<\2>/\1+\2+/;t1
s/[<>]//g
s/:}/>/g;s/:{/</g;s/::/:/g'
これは、各行で独立してこれを実行すると仮定します。フルファイルに対してこれを行うには、まずファイル全体をメモリにロードする必要があります(一部のsed
実装にはサイズ制限があります)。
sed '
:2
$!{N;b2
}
s/:/::/g;s/</:{/g;s/>/:}/g
s/[[:alnum:]]\{1,\}/<&>/g;:1
s/\(<\([^>]*\)>.*\)<\2>/\1+\2+/;t1
s/[<>]//g
s/:}/>/g;s/:{/</g;s/::/:/g'
ただし、これは非常に非効率的で、使いやすくなりますperl
。
perl -pe 's/\w+/$seen{$&}++ ? "+$&+" : $&/ge'
ラインベース:
perl -pe 'my %seen;s/\w+/$seen{$&}++ ? "+$&+" : $&/ge'
答え2
別のアプローチは次のとおりです。これはいくつかのsed
sを使用します。
an='[:alnum:]' esc=$(printf '\033\[')
sed "/[${an}]/!d;=;a\ }
s/.*/ & /;s/[^${an}]\{1,\}/ /g
s| \([${an}"']\{1,\}\) | \
s/\\([^+'"${an}"']\\)\\(\1\\)\\([^+'"${an}"']\\)/\\1+\\2+\\3/2|g
' <text |
sed '/^ /!N;s/\n */{/' |
sed -e 's/.*/ & /;s/+/ & /g' \
-f - \
-e "s/ //;s/ $//
s/+[^+ ]\{1,\}+/${esc}38;5;35m&${esc}0m/g
s/ + /+/g" text
基本的に、最初の2つのsed
チームは一緒に協力して3番目のスクリプトを作成しました。最初は、sed
各行の英数字以外のすべての項目を消去し、行のない行は完全にスキップします。残りのすべての文字グループに対して代替文を作成し、3 番目の文字は終了します。(ほぼ即座に)スクリプトを読んで解釈してください。
2番目のスクリプトは、sed
最初のスクリプトが1行ずつ作成されるため、必要であり、1行に複数のステートメントがある可能性がありますs///
。最初は英数字を含む各行の行番号を印刷しますが、3番目の関数コンテキスト内でペアを指定する必要があるため、2番目はsed
そうします。
以下はスクリプトの例です。
...
43{
s/\([^+[:alnum:]]\)\(n\)\([^+[:alnum:]]\)/\1+\2+\3/2
s/\([^+[:alnum:]]\)\(N\)\([^+[:alnum:]]\)/\1+\2+\3/2
s/\([^+[:alnum:]]\)\(G\)\([^+[:alnum:]]\)/\1+\2+\3/2
}
44{
s/\([^+[:alnum:]]\)\(b\)\([^+[:alnum:]]\)/\1+\2+\3/2
s/\([^+[:alnum:]]\)\(block\)\([^+[:alnum:]]\)/\1+\2+\3/2
}
45{
s/\([^+[:alnum:]]\)\(END\)\([^+[:alnum:]]\)/\1+\2+\3/2
s/\([^+[:alnum:]]\)\(SEDSCRIPT\)\([^+[:alnum:]]\)/\1+\2+\3/2
}
2
それぞれに末尾がありますs///
。これは、各置換が各パターンの第2の発生に対するものであるからである。 2番目の発生が存在しない場合、交換は行われません。上記は私の他のスクリプトで実行した結果です。sed
特殊文字や類似文字の影響を受けないようです。
文章を書いて選択項目に色を付けると、何が起こっているのかをより簡単に知ることができます。
s/+[^+ ]\{1,\}+/${esc}38;5;35m&${esc}0m/g
...その行はそうです。コメントを付けたり削除したりすることができます(以前使用していましたが、不要または不要)。
サンプルデータ用に作成するスクリプトは次のとおりです。
1{
s/\([^+[:alnum:]]\)\(qq\)\([^+[:alnum:]]\)/\1+\2+\3/2
s/\([^+[:alnum:]]\)\(ab\)\([^+[:alnum:]]\)/\1+\2+\3/2
s/\([^+[:alnum:]]\)\(xyz\)\([^+[:alnum:]]\)/\1+\2+\3/2
s/\([^+[:alnum:]]\)\(ab\)\([^+[:alnum:]]\)/\1+\2+\3/2
s/\([^+[:alnum:]]\)\(qq\)\([^+[:alnum:]]\)/\1+\2+\3/2
s/\([^+[:alnum:]]\)\(aa\)\([^+[:alnum:]]\)/\1+\2+\3/2
s/\([^+[:alnum:]]\)\(ab\)\([^+[:alnum:]]\)/\1+\2+\3/2
}
印刷される内容は次のとおりです。
qq ab xyz +ab+ +qq+ aa +ab+
sed
そして私の以前のスクリプトのいくつかは次のとおりです。
s/\(\(.\)${bs}\2\)\{1,\}/${esc}38;5;35m&${+esc+}0m/g
s/\(_${bs}[^_]\)\{1,\}/${esc}38;5;75m&${+esc+}0m/g
s/.${bs}//g
s/\(\(${esc}\)0m\2[^m]*+m+[_ ]\{,+2+\}\)\{+2+\}/_/g
n; /./!N;G