多くの文字列操作チュートリアルを見つけましたが、それらを私の特定の状況に適用する方法を理解できません。文字列変数Wordをテキスト変数に挿入する必要がありますTextどちらかの方法を使用します(行番号に依存しない、変数の操作は読み取り/書き込みよりも優先されます)ファイル):
特定のインデックス(バイト位置)
text="mytextMATCHmytext"
Word="Word"
match="MATCH"
# method1 - not working, because text is not a file
sed '/$Word/ i $match' text
# method2
indx="${text%%$match*}"
indx=${indx%:*} # leave only the byte index where match starts
text="$text{0-$index-1}$Word$text{$index-end}"
# expected value of text:
"mytextWORDMATCHmytext"
構文を理解するのを助けてください。両方の方法を修正するとよいでしょう。それを行う他の方法は? textには1MBを超えるテキストが含まれるため、効率的な方法が推奨されます。
テキストj
を変数text
の位置p
に挿入するには(ゼロから数えます):
p=5
text="$(seq 10)" ## arbitrary text
text="${text:0:p}j${text:p}"
$match
の一致部分の前にテキストj
を挿入するには:
text="${text%%${match}*}j${match}${text##*${match}}"
これは、$text
が見つかるまで$match
の先頭部分を引き出し、次にj
、次に$match
、最後に$text
の末尾部分を追加します。 $match
を見つけます。 $match
の$text
の一致は1つだけです。
操作を確実に実行するには、次の文字列操作ルーチンが必要です。
text_new=${text%%"${match}"*}${Word}${text#*"${text%%"${match}"*}"}
# |------- A -------| |-B--| |------------ C -------------|
A
は、一致前の部分、つまり、一致が始まる前の文字列です。B
は挿入するデータです。C
は、試合後の部分、つまり試合終了後の文字列です。bash
parameter expansion
ルーチンがメタ文字を認識しないように、一致文字列は引用符で囲まれていることに注意してください。match_esc=$(printf '%s\n' "$match" | sed -e 's|[][^\/.*$]|\\&|g' | sed -e 'H;1h;$!d;g;s/\n/\\n/g')
Word_esc=$(printf '%s\n' "$Word" | sed -e 's|[\&/]|\\&|g;$!s/$/\\/')
printf '%s\n' "$text" | sed -e 'H;1h;$!d;g;'"s/$match_esc/$Word_esc&/"''
sed
メソッドは、sed
に意味があり、入力テキストに表示されるすべての文字をサイレントにする必要があるため、より回路的です。もう1つの複雑なレベルは、これらの文字がsedのs ///コマンドのLHSとRHSで異なることです。あなたが言うように、変数ではなくファイルにデータがある場合、それを直接sed
することはできません。ただし、それでも、要求したことを実行する簡単な方法です。あなたはそれをパイプライン化する必要があるだけです:
#!/usr/local/bin/bash
text="loremipsumNEEDLEdolorsitamet"
Word="HAYSTALK"
match="NEEDLE"
echo "$text" | sed "s/$match/&$Word/g"
実証的な出力:
$ ./369818.sh
loremipsumNEEDLEHAYSTALKdolorsitamet