Préfixe et suffixe des chaînes à chaque ligne de sortie de la commande

17

J'ai rencontré un problème en essayant d'écrire un script Bash. Lors de la grepsortie, il renvoie (généralement) de nombreuses lignes. Je voudrais préfixer et suffixer une chaîne à chacune de ces lignes de sortie.

Je voudrais aussi noter que je tuyauterie lsen grep, comme:

ls | grep
SpecialBomb
la source
2
Vous ne devriez pas analyser ls- c'est du mauvais juju. De plus, cela doit-il être grep? Et pouvez-vous donner un exemple de sortie?
Sobrique
1
Que voulez-vous que votre script fasse si le nom de fichier contient une nouvelle ligne?
Tai Viinikka

Réponses:

27

Avec sed:

ls | grep txt | sed 's/.*/prefix&suffix/'
Cyrus
la source
3
Ou, sedétant un surensemble de grep: ls | sed -n '/txt/s/.*/prefix&suffix/p'ouls | sed -n 's/.*txt.*/prefix&suffix/p'
Stéphane Chazelas
@ StéphaneChazelas: Merci pour cet indice.
Cyrus
5

Avec sed:

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

Mais notez que cela souffre de problèmes avec les noms de fichiers avec des sauts de ligne et tous les problèmes assortis d'analyse syntaxique, lsce qui est généralement une mauvaise idée.

Avec perl

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

Remarque - perl greppeut prendre un modèle - comme la grepcommande, mais vous pouvez également faire des choses comme appliquer des tests de fichiers.

Par exemple

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

Dans grepl'itérateur par défaut $_est défini sur la valeur actuelle de l'élément, vous pouvez donc appliquer sed/ grepstyle regex, ou effectuer une variété de tâches basées sur $_.

Sobrique
la source
Comment pourrais-je inclure une variable comme suffixe / préfixe dans votre premier exemple en utilisant ´sed´?
SpecialBomb
Remplacez les guillemets par et utilisez simplement em.
Sobrique
2

Dans ce cas, GNU findvous permet de faire toutes ces choses en une seule fois, en éliminant les canaux et l'analyse potentiellement gênante de ls:

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

(ce findn'est pas un bon moyen de modifier arbitrairement la sortie d'autres commandes, bien sûr!)

Quelques notes:

  • -maxdepth 1et -name [^.]*faire fonctionner l'appariement des noms de la même manière qu'une plainels (ou ls .). Vous pouvez utiliser n'importe quel glob de style shell, mais notez que "*" correspondra à un "". dans un nom différent bash, [^.]*signifie donc tout ce qui n'a pas de "."
  • MYPATTERN est un ERE POSIX approprié (le type par défaut est Emacs, voir ici ), mais il doit correspondre au nom de fichier entier, donc utilisez quelque chose comme .*thing.*au lieu de simplementthing
  • vous pouvez probablement simplement utiliser l'un des -name/ -regexau lieu des deux (par exemple -regex "[^.]. MYPATTERN. "
  • -printf les soutiens beaucoup de choses , %nest le nom de fichier ou de répertoire sans fioritures

(cela peut toutefois dépendre de votre version find, consultez la section "CONFORMITÉ AUX NORMES" de votre page de manuel)

Comme alternative possible sans aucun programme externe requis, bash a compgenqui, entre autres, étend les globs, équivalent à un lssans options:

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

Cela gère les noms de fichiers avec des espaces, y compris les retours à la ligne. compgen -G "*"devrait fournir la même sortie qu'un simple ls(mais notez que ls *c'est une chose complètement différente). Vous aurez toujours besoingrep , et cela peut ou non résoudre le problème, mais cela vaut la peine d'être mentionné.

Mr Spuratic
la source
0

sedet les findsolutions sont contestées si votre préfixe / suffixe comprend des caractères de clé d'expression régulière ou si vous souhaitez passer une variable d'environnement (au lieu d'une valeur immédiate), xargs+ echopourrait être plus approprié ici.

Avec variable d'environnement:

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

Avec un inline:

ls | grep p | xargs -I % sh -c "echo `pwd`/%"
lashgar
la source