web-dev-qa-db-fra.com

Sélectionner / Sélectionner manuellement des lignes avant de transférer à stdout

Y a-t-il un moyen de grep de manière interactive, ce qui signifie que j'ai une bande de lignes provenant d'un endroit où je veux tuyer un traitement ultérieur, avec la possibilité de spécifier manuellement les lignes que je veux?

Considérez cet exemple:

#Name   Food    Music
Adam    Cake    Rock
Bert    Fruit   Folk
Caesar  Cake    Rock
Doris   Cake    Folk
Emil    Fruit   Rock
Francis Fruit   Folk
Gertrud Cake    Rock
...

Je peux prendre ce fichier et filtrer à l'aide de lignes comme

cat people.txt | grep -v "^#" | grep "^.*Fruit.*Folk"

... Pour que toutes les personnes invitaient à une fête folklorique de légumes. Quand j'attache cela plus loin:

cat people.txt | grep -v "^#" | grep "^.*Fruit.*Folk" | ??? | peopleInviterScript

... Je veux avoir un certain ??? Dans le tuyau qui me donne la possibilité de sélectionner/désélectionner des personnes avant l'envoi des invitations.

Y a-t-il déjà un tel outil à Bash/ZSH, je ne sais tout simplement pas?

17
Bowi

Bien que j'aime l'approche vipe, j'ai trouvé une manière encore plus fraîche: FZF .

cat people.txt | grep -v "^#" | grep "^.*Fruit.*Folk" | fzf -m | cat

... donne une belle liste où je peux rechercher et basculer les objets avec le clavier et disparaître complètement quand je suis terminé.

21
Bowi

pLUSTILS a vipe, qui exploite simplement votre éditeur de texte régulier (VI ou quelque chose) dans le cadre du pipeline. Toute lignes que vous ne supprimez pas sera écrite à STDOUT. (En général, cependant, vous obtenez le même résultat en redirigeant dans un fichier temporaire et en modifiant ce fichier.)

18
user1686

Vous pouvez également utiliser gvim (et vim) pour cela. Insérer gvim /dev/stdin dans votre tuyau et écrivez en faisant :wq! /dev/stdout Lorsque vous avez fini de modifier.

Appeler GVIM Comme ce qui suit vous permet d'écrire plus naturellement et de fermer avec ZZ:

gvim +'nmap ZZ :wq!<cr> | r /dev/stdin | 1d | file /dev/stdout'

Vous pouvez faire un alias ou une fonction de cela:

gvimp() {
  gvim +'
    nmap ZZ :wq!<cr>
    r /dev/stdin
    1d
    file /dev/stdout
  '
}

Voici un exemple où j'ai supprimé les lignes 4-7 et fini en faisant ZZ en mode normal:

$ seq 1 10 | gvimp | sed -r 's/^|$/=/g'
=1=
=2=
=3=
=8=
=9=
=10=

EDIT: Vim régulier est un peu plus difficile, car il utilise STDIN pour l'entrée du clavier et STDOUT pour dessiner l'interface utilisateur. Cependant, vous pouvez toujours l'utiliser en ajoutant un processus supplémentaire. Vous redirigez la STD de Vim * sur le terminal et utilisez le processus parent 'std * pour le tuyau de données.

vimp() {
  bash -c '
    terminal="/dev/$(ps -o tty= $$)"
    tmp_out="$(mktemp)"
    trap "rm \$tmp_out" EXIT
    vim <(cat) < "$terminal" &> "$terminal" +"
      file $tmp_out
      set noreadonly
      nmap ZZ :wq!<cr>
    "
    cat "$tmp_out"
  '
}

Le fichier temporaire est nécessaire car sinon la sortie de tuyau va être mélangée à l'interface utilisateur de VIM et pourrait disparaître avec elle lorsque Vim sort.

5
JoL