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

17

Ocorreu um problema ao tentar escrever um script Bash. Quando grepsai, retorna (geralmente) muitas linhas. Gostaria de prefixar e sufixar uma string para cada uma dessas linhas de saída.

Gostaria também de notar que eu estou canalizando lspara grep, como:

ls | grep
SpecialBomb
fonte
2
Você não deve analisar ls- é ruim juju. Além disso, tem que ser grep? E você pode dar um exemplo de saída?
Sobrique
1
O que você deseja que seu script faça se o nome do arquivo contiver uma nova linha?
Tai Viinikka

Respostas:

27

Com sed:

ls | grep txt | sed 's/.*/prefix&suffix/'
Cyrus
fonte
3
Ou, sedsendo um superconjunto de grep: ls | sed -n '/txt/s/.*/prefix&suffix/p'ouls | sed -n 's/.*txt.*/prefix&suffix/p'
Stéphane Chazelas
@ StéphaneChazelas: Obrigado por esta dica.
Cyrus
5

Com sed:

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

Mas observe que isso sofre de problemas com nomes de arquivos com feeds de linha e de todos os problemas variados de análise, o lsque geralmente é uma má idéia.

Com perl

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

Nota - o perl greppode ter um padrão - como o grepcomando, 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. 

No grepiterador padrão, $_é definido o valor atual do elemento, para que você possa aplicar sed/ grepregex de estilo ou executar uma variedade de tarefas com base em $_.

Sobrique
fonte
Como incluiria uma variável como sufixo / prefixo no seu primeiro exemplo usando 'sed'?
SpecialBomb
Mude as aspas para e use-as.
Sobrique
2

Nesse caso, o GNU findpermite que você faça todas essas coisas de uma só vez, eliminando pipes e a análise potencialmente problemática de ls:

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

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

Algumas notas:

  • -maxdepth 1e -name [^.]*faça com que a correspondência de nomes funcione da mesma forma que uma planície ls(ou ls .). Você pode usar qualquer glob no estilo de shell, mas observe que "*" corresponderá a um "" inicial. em um nome diferente de bash, [^.]*significa qualquer coisa que não tenha um "." inicial
  • MYPATTERN é um POSIX ERE adequado (o tipo padrão é Emacs, veja aqui ), mas deve corresponder ao nome do arquivo inteiro, portanto, use algo como em .*thing.*vez de apenasthing
  • você provavelmente pode usar apenas um de -name/ em -regexvez de ambos (por exemplo, -regex "[^.]. MYPATTERN. "
  • -printfsuporta muitas coisas , %né o nome do arquivo ou diretório sem adornos

(isso pode depender da sua versão find, verifique a seção "CONFORMIDADE PADRÃO" da sua página de manual)

Como uma alternativa possível sem a necessidade de programas externos, bashpossui compgen, dentre outras coisas, a expansão de globs, equivalente a uma lsopção sem opções:

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

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

mr.spuratic
fonte
0

sed e find soluções são contestadas se seu prefixo / sufixo incluir caracteres-chave de expressão regular ou se desejar passar uma variável de ambiente (em vez de um valor imediato), xargs+ echopode 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`/%"
lashgar
fonte