Exclua a série consecutiva mais longa de caracteres da frente ou de trás

Exclua a série consecutiva mais longa de caracteres da frente ou de trás

Por exemplo, uma string tem: aaaaabbaabaabbaa, quero apará-la para que exclua todos os "a" da frente até "b", então o resultado deve ser bbaabaabbaa.

Responder1

Dê uma olhada nas seçõesExpansão de parâmetroseCorrespondência de padrõesem man 1 bash:

$ shopt -s extglob # enable extended glob operators
$ s=aaaaabbaabaabbaa
$ echo "${s##*(a)}"
bbaabaabbaa

$ s=bananasssssssss
$ echo "${s%%*(s)}"
banana

Responder2

Com GNU sed:

sed -e 's/^\(.\)\1\{1,\}//'

que corresponde e exclui qualquer caractere que se repita pelo menos uma vez no início de uma linha. ele usa ^\(.\)para corresponder ao primeiro caractere e, em seguida, \1\{1,\}para corresponder 1 ou mais com referência anterior a essa correspondência.

Se você deseja corresponder apenas 1 ou mais repetições do primeiro caractere, você pode usar apenas sed -e 's/^\(.\)\1\+//', mas o \{1,\}formulário pode ser facilmente modificado para 2 ou mais ou 3 ou mais, etc., se necessário.

Responder3

Apenas duas linhas:

$ a="aaaaabbaabaabbaaddd" 
$ echo "${a#"${a%%[^"${a:0:1}"]*}"}"
bbaabaabbaaddd

Ação explicada:

                  "${a:0:1}"         ## Select the first char of $a: ='a'
                [^          ]*       ## All chars not 'a' from the end. ='bbaabaabbaaddd'
          "${a%%              }"     ## Remove 'bbaabaabbaaddd' from the end of $a. ='aaaaa'  
echo "${a#                      }"   ## Remove 'aaaaa' from start of $a and echo it.

(-)Ambas as expansões precisam de aspas para lidar corretamente com * e /. Ainda existe o problema de que as crases geralmente são processadas incorretamente:

a="\\\\*\\\\*****vdf*"; echo "${a#"${a%%[^"${a:0:1}"]*}"}"

Irá imprimir:

*\\*****vdf*

A string inicial repetida foi removida corretamente, mas as quatro barras invertidas seguintes foram transformadas em apenas duas.

informação relacionada