Qual é o conceito de Shortest Sub-string Match no Unix Shell?

2

Estou usando o script a seguir para Correspondência de sequência secundária mais curta no tratamento de strings.

filename="bash.string.txt"

echo ${filename#*.}

Apresenta a seguinte saída.

string.txt

Aqui está uma explicação do exemplo acima (Link: link ):

The above example deletes the shortest match of $substring from front of $string. In the first echo statement substring ‘*.’ matches the characters and a dot, and # strips from the front of the string, so it strips the substring “bash.” from the variable called filename.

Então eu mudei o código como abaixo:

filename="bashshell.string.txt"

echo ${filename#*.}

Eu apenas estendi a primeira string de bash para bashshell . e esperando a saída "bashshell.txt" de acordo com a explicação dada acima. Mas em vez disso, me dá a mesma saída do primeiro exemplo.

i.e. string.txt

Então eu entendi errado o conceito? Se sim do que realmente funciona?

    
por Dip 07.08.2018 / 14:31

2 respostas

3

So do I misunderstood the concept? If yes than how it actually works?

Sim, a notação ${var#*.} está removendo tudo, desde o início da string até o ponto de caractere ( . ). Está fazendo o que você pediu, seu padrão era ponto estrela:

*.

Portanto, ele corresponderá a todos os itens até o 1º ponto do início da string, aquele após a palavra bash .

bash.string.txt
    ^---------------- it's splitting here

Exemplos

$ str="bash.string.txt"
$ echo "${str#*.}"
string.txt

$ str="bash1.string.txt"
$ echo "${str#*.}"
string.txt

$ str="bash1.string1.txt"
$ echo "${str#*.}"
string1.txt

Veja quando eu coloquei o 1 no lado esquerdo do primeiro . . Essa notação está truncando tudo até o primeiro ponto.

    
por 07.08.2018 / 14:53
2

O uso da palavra-chave "substring" pelo tutorial é um pouco enganador. Ao usar ${variable#pattern} , estamos lidando com a correspondência e a exclusão de uma sequência de prefixo (e com ${variable%pattern} a seqüência de sufixo ).

Você removeu a string de prefixo mais curta correspondente a *. das duas strings bash.string.txt e bashshell.string.txt . O resultado de ambas as strings é o mesmo, string.txt , porque o padrão *. corresponde ao primeiro ponto da string, inclusive.

O padrão POSIX define essa expansão de parâmetro específica como

${parameter#[word]}

Remove Smallest Prefix Pattern. The word shall be expanded to produce a pattern. The parameter expansion shall then result in parameter, with the smallest portion of the prefix matched by the pattern deleted. If present, word shall not begin with an unquoted #.

Se você quisesse obter o resultado bashshell.txt , teria de remover a string .string ou string. do meio da string. Isso pode ser feito em duas etapas com expansões de parâmetros padrão:

suffix=${filename##*.}          # remove everything to the *last* dot
echo "${filename%%.*}.$suffix"  # remove everything from the first dot and add suffix

As variações ## e %% da expansão do parâmetro removem as cadeias de prefixo e sufixo correspondentes mais longas , respectivamente.

Como alternativa, com bash :

echo "${filename/string./}"

Isso remove a (primeira ocorrência da) string dada em qualquer lugar dentro do valor de $filename .

    
por 07.08.2018 / 14:38