テキストファイルの各行にある部分文字列の一部のインスタンスを変更する必要があります。これらのインスタンスはすべて連続的です(例:3〜6または2〜5など)。このタスクにはどのようなコマンドが必要ですか?私が得た最も近いものは次のとおりです。
sed 's/this/that/3' file1
これは3回目だけ状況を変えます。同じことがあってほしい
sed 's/this/that/3,6' file1
答えかもしれませんが、sed
範囲は表示されません。
入力例:
I want to change all letters "a" to "w" starting from the word "all" until the second "all" (inclusive)
予想出力:
I want to change wll letters "w" to "w" stwrting from the word "wll" until the second "all" (inclusive)
答え1
そしてperl
:
3番目から6番目のa
sをsに変更しますb
。
$ echo aaaaaaaaa | perl -pe '$n=0; s{a}{++$n;$n==3..$n==6?"b":$&}ge'
aabbbbaaa
これは演算子e
のフラグを使用するため、置換はs{regex}{replacement}flags
コードとして評価されます。これは、インクリメントされ"b"
たカウンタが3から6の間で提供され、$&
それ以外の場合は一致する値()が提供されます。または:
$ echo aaaaaaaa | perl -pe '$n=0; s/a(?(?{++$n; $n == 3 .. $n == 6})|(*FAIL))/b/g'
aabbbbaa
増加するカウンタが3〜6の範囲にない場合は、情報を(?(condition)yes|no)
提供する正規表現演算子を使用してください。(*FAIL)
GNUは3番目とそれ以降のアイテムの交換をsed
サポートしています。s/foo/bar/3g
foo
したがって、次の固定文字列の場合は、次のようにします。
$ echo aaaaaaaaa | sed 's/a/\n/3g;s/\n/a/5g;s/\n/b/g'
aabbbbaaa
つまり、最後の改行文字a
から3番目の文字を改行文字に置き換え(パターンスペースで他の状況が発生しないように)、最後の改行文字から5番目の文字をs(6 - 3 + 1 = 4)に戻します。 。必要なa
s)の数a
に応じて、次の項目を復元してから、残りのb
改行をすべてsに置き換えます。
何でもsed
:
sed 's/a/\
/g
s/\n/b/3
s/\n/b/3
s/\n/b/3
s/\n/b/3
s/\n/a/g'
最初の 2 つの発生の間の s をa
s に変更するには、次のようにします。w
all
$ echo aaallaaallaaa | perl -pe 's{all.*?all}{$& =~ s/a/w/gr}e'
aawllwwwllaaa
\b
all
分離が必要な場合は、単語境界演算子を使用してください。性格。
$ echo 'alloy (all-hands aaa ball all) fall' | perl -pe 's{all.*?all}{$& =~ s/a/w/gr}e'
wlloy (wll-hands aaa ball all) fall
$ echo 'alloy (all-hands aaa ball all) fall' | perl -pe 's{\ball\b.*?\ball\b}{$& =~ s/a/w/gr}e'
alloy (wll-hwnds www bwll wll) fall
(-Mopen=locale
ASCIIのみと仮定するのではなく、ロケール文字マップに従ってデコードする文字を追加します。たとえば、allée
フランス語の単語をUTF-8にエンコードし、all
後に単語以外の文字が続きません。)
答え2
ではこれは不可能かもしれませんが、sed
次のGNUawk
プログラムはうまくいきます:
awk -v frst=2 -v lst=5 '{for (i=1; i<=(lst-frst+1);i++) $0=gensub(/a/,"w",frst)}1'
- これにより、最初と最後の項目が置き換えられる変数
frst
sumに渡されます。lst
awk
- 次に、行内の検索パターンの-番目の発生を
gensub()
置き換え、結果を現在の行バッファに再割り当てするために使用されます。frst
lst-frst+1
必要なすべてのイベントを置き換えるために合計()回実行されます。次に、現在の行を印刷します(すべての修正を含む)。- 置き換えられたアイテムは次のループ反復に含まれなくなり、置換される文字列内のアイテムの数は常に変わりません。
適用例:
$ echo "a1a2a3a4a5a6" | awk -v frst=2 -v lst=5 '{for (i=1; i<=(lst-frst+1);i++) $0=gensub(/a/,"w",frst)}1'
a1w2w3w4w5a6
またはテキスト:
$ echo 'I want to change all letters "a" to "w" starting from the word "all" until the second "all" (inclusive)' | awk -v frst=3 -v lst=6 '{for (i=1; i<=(lst-frst+1);i++) $0=gensub(/a/,"w",frst)}1'
I want to change wll letters "w" to "w" stwrting from the word "wll" until the second "all" (inclusive)
いつものように、検索パターンが重複する可能性がある場合、期待どおりに動作しません。
答え3
いくつかの奇妙な場合:
awk -v FS='a' -v start=3 -v end=6 -v replace="w" '
{
for(i=1; i<NF; i++)
printf("%s", $i (start<=i && i<=end? replace: FS))
print $NF
}' infile
ここではFS=a
awk に文字に基づいてレコードを分割するよう指示し、a
他の awk 変数も次のように定義します。スタート、終わりそして変えるはそれぞれターゲット文字「a」の開始位置と終了位置であり、これを「w」文字に置き換えます。
その後、フィールドを繰り返し、フィールド自体を印刷します。フィールド番号が始点と終点の間にある場合はフィールド自体を印刷し、そうでない場合は文字「a」を印刷します。最後に最後のフィールドも出力します。
答え4
使用幸せ(以前のPerl_6)
~$ echo aaaaaaaa | perl6 -pe 's:nth(3..6)/a/b/;'
aabbbbaa
Raku (Perl 系列のプログラミング言語) には、等の同義語をnth
サポートする新しい正規表現修飾子 ("位置副詞") があります。一般的な代替目的のために、数値または範囲引数を挿入します。1st
2nd
3rd
nth()
上記のバージョンはクイックバージョンです。これは、Rakuの正規表現修飾子がどのように直感的であるかを示すためのものです(テーマ変数を再ロードするために使用されるたびに、、の6th
一致5th
が4th
連続3rd
的に置き換えられます)。andthen
$_
~$ echo aaaaaaaa | perl6 -ne 'S:6th/a/b/ andthen S:5th/a/b/ andthen S:4th/a/b/ andthen S:3rd/a/b/ andthen .put;'
aabbbbaa
https://docs.raku.org/言語/regexes#Positional_adverbs
https://raku.org