Como inserir uma string em uma variável de texto na posição especificada

1

Encontrei muitos tutoriais de manipulação de strings, mas não consigo descobrir como aplicá-los à minha situação específica. Eu preciso inserir (não substituir) uma variável de string palavra em uma variável de texto texto usando qualquer método (não pode depender da numeração de linha, manipulação variável preferida sobre leitura / gravação para um arquivo):

  1. Antes da string correspondente ou
  2. Em um índice específico (posição de byte)

    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"
    

Por favor, ajude a descobrir a sintaxe. Seria bom corrigir os dois métodos. Alguma outra maneira de fazer isso? O texto contém > 1MB de texto, por isso, o modo eficiente é o preferido.

    
por Nazar 07.06.2017 / 20:53

3 respostas

4

Para inserir o texto j na variável text na posição p (contando de zero):

p=5
text="$(seq 10)"               ## arbitrary text
text="${text:0:p}j${text:p}"

Para inserir o texto j antes da parte correspondente em $match :

text="${text%%${match}*}j${match}${text##*${match}}"

Isso extrai a parte inicial de $text até encontrar $match , depois adiciona j , depois $match e, em seguida, a parte final de $text até encontrar $match . Espero que haja apenas uma correspondência de $match em $text !

    
por 07.06.2017 / 21:02
2

Você precisa das seguintes rotinas de manipulação de strings para realizar a operação de forma confiável:

text_new=${text%%"${match}"*}${word}${text#*"${text%%"${match}"*}"}
#         |------- A -------| |-B--| |------------ C -------------|
  • A é a parte pré-correspondência, ou seja, a string antes do início da partida.
    • É gerado por, parado no final da string, olhando para o início da string, e rasgando até e incluindo o último avistamento do texto da partida.
  • B são os dados a serem inseridos.
  • C é a parte pós-correspondência, ou seja, a sequência após o término da partida.
    • É gerado por, parado no começo da corda, olhando para o final da corda, e rasgando até a primeira aparição do que foi o resultado da Etapa A.
  • Observe que a sequência de correspondência é citada para evitar que quaisquer metacaracteres sejam compreendidos pelas rotinas bash parameter expansion .
  • É dada a devida consideração à possibilidade de a partida estar presente mais de uma vez na sequência. A primeira partida da esquerda é substituída.
  • O caso de uma string com novas linhas também é tratado.

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&/"''
  • O método sed é mais tortuoso, já que precisamos garantir que todos os caracteres com significado em sed e que apareçam no texto de entrada sejam silenciados. Outro nível de complicação é que esses caracteres são diferentes para LHS e RHS do comando s /// do sed.
  • Identificar esses caracteres e silencia-los formam o próximo passo.
  • Depois disso, é uma simples questão de executar os dados de texto através do habitual material sed / ///.
por 08.06.2017 / 22:17
1

Como você disse, se você tiver os dados em uma variável e não em um arquivo, não poderá sed diretamente. No entanto, ainda é a maneira simples de fazer o que você pede; você só precisa canalizar:

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

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

Saída demonstrativa:

$ ./369818.sh
loremipsumNEEDLEHAYSTALKdolorsitamet
    
por 07.06.2017 / 21:54