web-dev-qa-db-ja.com

文字列をテキスト変数の指定した位置に挿入する方法

多くの文字列操作チュートリアルを見つけましたが、それらを私の特定の状況に適用する方法を理解できません。文字列変数Wordをテキスト変数に挿入する必要がありますTextどちらかの方法を使用します(行番号に依存しない、変数の操作は読み取り/書き込みよりも優先されます)ファイル):

  1. 一致した文字列の前、または
  2. 特定のインデックス(バイト位置)

    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を超えるテキストが含まれるため、効率的な方法が推奨されます。

5
Nazar

テキスト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つだけです。

11
Jeff Schaller

操作を確実に実行するには、次の文字列操作ルーチンが必要です。

text_new=${text%%"${match}"*}${Word}${text#*"${text%%"${match}"*}"}
#         |------- A -------| |-B--| |------------ C -------------|
  • Aは、一致前の部分、つまり、一致が始まる前の文字列です。
    • これは、文字列の最後に立ち、文字列の先頭に向かって見て、一致するテキストの最後の目撃までを含めて生成されます。
  • Bは挿入するデータです。
  • Cは、試合後の部分、つまり試合終了後の文字列です。
    • これは、文字列の先頭に立って、文字列の終わりに向かって見て、Step-Aの結果が何であるかを最初に目撃するまで含めて生成されます。
  • bashparameter expansionルーチンがメタ文字を認識しないように、一致文字列は引用符で囲まれていることに注意してください。
  • 一致が文字列内に2回以上存在する可能性を十分に考慮します。左から最初の一致が置換されます。
  • 改行を含む文字列の場合も処理されます。

Sed

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 s ///でsedからテキストデータを実行するだけです。
4
user218374

あなたが言うように、変数ではなくファイルにデータがある場合、それを直接sedすることはできません。ただし、それでも、要求したことを実行する簡単な方法です。あなたはそれをパイプライン化する必要があるだけです:

#!/usr/local/bin/bash
text="loremipsumNEEDLEdolorsitamet"
Word="HAYSTALK"
match="NEEDLE"

echo "$text" | sed "s/$match/&$Word/g"

実証的な出力:

$ ./369818.sh
loremipsumNEEDLEHAYSTALKdolorsitamet
1
DopeGhoti