Cadeias de prefixo e sufixo para cada linha de saída do comando

12

Eu encontrei um problema ao tentar escrever um script Bash. Quando grep gera, retorna (geralmente) muitas linhas. Eu gostaria de prefixar e sufixar uma string para cada uma dessas linhas de saída.

Eu também gostaria de observar que estou canalizando ls para grep , como:

ls | grep
    
por SpecialBomb 24.12.2015 / 20:03

4 respostas

19

com sed:

ls | grep txt | sed 's/.*/prefix&suffix/'
    
por 24.12.2015 / 23:24
5

com sed :

ls | grep pattern | sed -e 's/^/prefix/' -e 's/$/suffix/'

Mas note que isso sofre de problemas com nomes de arquivos com feeds de linha e todos os problemas de análise de ls , o que geralmente é uma má ideia.

com perl

perl -e 'print "prefix".$_."suffix\n" for grep { m/somepattern/} glob "*"'

Nota - perl grep pode pegar um padrão - como o comando grep , mas você também pode fazer coisas como aplicar testes de arquivo.

Por exemplo

grep {-d} glob "*" #filters directories.
grep { (stat)[9] > time() - 60 } glob "*" #reads file mtime and compares. 

Dentro de grep , o iterador padrão $_ é definido como o valor do elemento atual, portanto você pode aplicar sed / grep style regex ou executar uma variedade de tarefas com base em $_ .

    
por 24.12.2015 / 20:52
2

Neste caso, o GNU find permite que você faça tudo isso de uma só vez, eliminando os canais e analisando potencialmente os problemas de ls :

find . -maxdepth 1 -name '[^.]*' \
  -regextype posix-extended -regex "MYPATTERN" \
  -printf 'SOMEPREFIX %f SOMESUFFIX\n'

( find não é uma boa maneira de modificar arbitrariamente a saída de outros comandos, é claro!)

Algumas notas:

  • -maxdepth 1 e -name [^.]* fazem a correspondência de nome funcionar da mesma forma que uma ls (ou ls . ) simples. Você pode usar qualquer glob de shell, mas observe que "*" corresponderá a um "." Principal. em um nome ao contrário de bash , então [^.]* significa qualquer coisa que não tenha um "".
  • MYPATTERN é um POSIX ERE adequado (o tipo padrão é Emacs, consulte aqui ), mas ele deve corresponder ao nome do arquivo inteiro, então use algo como .*thing.* em vez de apenas thing
  • você pode provavelmente usar apenas um dos -name / -regex em vez de ambos (por exemplo, -regex "[^.]. MYPATTERN. "
  • -printf suporta muitas coisas , %n é o sem adornos nome do arquivo ou diretório

(this can depend on your version of find though, check the "STANDARDS CONFORMANCE" section of your man page)

Como uma alternativa possível sem a necessidade de programas externos, bash tem compgen , o que, entre outras coisas, expande globs, equivalente a ls sem opções:

compgen -P "someprefix>" -S "<somesuffix" -G "pattern"

Isso lida com nomes de arquivos com espaço em branco, incluindo novas linhas. compgen -G "*" deve fornecer a mesma saída que um ls simples (mas note que ls * é uma coisa totalmente diferente). Você ainda precisará de grep , e isso pode ou não resolver o problema, mas vale a pena mencionar.

    
por 23.02.2018 / 19:29
0
As soluções

sed e find são desafiadas se seu prefixo / sufixo incluir caracteres de chave de expressão regular ou se desejar passar uma variável de ambiente (em vez de um valor imediato), xargs + echo pode ser mais apropriado aqui .

Com variável de ambiente:

ls | grep p | xargs -I % sh -c "echo $PATH/%"

Com um inline:

ls | grep p | xargs -I % sh -c "echo 'pwd'/%"
    
por 14.09.2018 / 20:32