Usando regex no loop for

0

Eu estou olhando para percorrer um diretório de arquivos e combiná-los com regex e, em seguida, substituir o caractere apropriado:

#somefile.txt
%somefile.txt
>somefile.txt

# arr=(\% \> \#) ;for f in *; do echo -- "$f" "${f//${arr[@]}/}"; done

deve ecoar:

#somefile.txt -- somefile.txt
%somefile.txt -- somefile.txt
>somefile.txt -- somefile.txt

em vez disso eu recebo:

#somefile.txt -- #somefile.txt
%somefile.txt -- %somefile.txt
>somefile.txt -- >somefile.txt

que resulta em nenhuma mudança, nada, zilch.

a matriz funciona se eu usar arr(\%) com um único caractere, o que anula todo o propósito.

#somefile.txt -- #somefile.txt
%somefile.txt -- somefile.txt
>somefile.txt -- >somefile.txt
    
por user68332 23.05.2014 / 04:34

2 respostas

2

A questão principal aqui é que ${PARAMETER/PATTERN/STRING} expansion PATTERN não aceita uma matriz como PARAMETER e, portanto, ${arr[@]} expande para "% > #" .

O efeito disso pode ser visto se você adicionar alguns arquivos:

# touch "% > #somefile.txt"
# touch "%>#somefile.txt"

Seu comando resultaria em:

#somefile.txt -- #somefile.txt
%somefile.txt -- %somefile.txt
>somefile.txt -- >somefile.txt
%>#somefile.txt -- %>#somefile.txt
% > #somefile.txt -- somefile.txt

A última linha mostra exatamente o que está acontecendo.

Outro sugeriu usar o piping $f a sed e fazer mágica lá, e isso seria uma boa opção, pois permitiria transformações mais complexas, no entanto assumindo que você só deseja remover os caracteres principais, usando o bash ${PARAMETER#WORD} expansão de parâmetros seria suficiente:

# gpat=" ;for f in *; do echo -- "$f" "${f#$gpat}"; done

Para mim, essa linha resulta em:

>somefile.txt -- somefile.txt
#somefile.txt -- somefile.txt
%somefile.txt -- somefile.txt
%>#somefile.txt -- >#somefile.txt
% > #somefile.txt --  > #somefile.txt

Estou chamando o padrão $gpat como é isso - uma festa padrão de globbing . Não é uma expressão regular.

Observe que ${PAR#WORD} não é voraz e corresponde ao padrão mais curto possível - ${PAR##WORD} corresponde ao padrão mais longo possível. No entanto, com gpat="[%>#]" , isso corresponderá a apenas um caractere:

# gpat="[%>#]" ;for f in *; do echo "$f" -- "${f##$gpat}"; done

%somefile.txt -- somefile.txt
>somefile.txt -- somefile.txt
#somefile.txt -- somefile.txt
%>#somefile.txt -- >#somefile.txt
% > #somefile.txt --  > #somefile.txt

Se tivermos a opção extglob shell configurada (verifique com shopt extglob , defina com shopt -s extglob , desative com shopt -u extglob - provavelmente será definido se você tiver um bashrc razoável), podemos usar a opção estendida padrões de globbing:

# gpat="+([%>#])" ;for f in *; do echo "$f" -- "${f##${gpat}}"; done

%somefile.txt -- somefile.txt
>somefile.txt -- somefile.txt
#somefile.txt -- somefile.txt
%>#somefile.txt -- somefile.txt
% > #somefile.txt --  > #somefile.txt

Notavelmente, em todos os exemplos acima, "% > #somefile.txt" se torna " > #somefile.txt" devido ao espaço após o% não ser capturado pelo padrão.

É claro que ${PARAMETER/PATTERN/STRING} (e o // similar) também aceitam padrões globbing, mas eu só percebi isso (literalmente) enquanto digito essas palavras, e eu realmente não consigo me incomodar em voltar acima para ajustá-lo para refletir isso. De qualquer forma, funciona exatamente da mesma forma e, claro, você só deseja usar PAR/PAT/ para remover caracteres do meio da cadeia.

    
por 23.05.2014 / 05:33
1

isso parece funcionar para mim ...

$ ls
#somefile.txt  %somefile.txt  >somefile.txt

$ for f in *; do j='echo $f | sed -e's/[\%\#\>]//g''; echo "$f -- $j"; done
#somefile.txt -- somefile.txt
%somefile.txt -- somefile.txt
>somefile.txt -- somefile.txt
    
por 23.05.2014 / 04:50

Tags