Forum Programmation.shell Utiliser la sortie d'une commande comme chaîne de recherche de awk

Posté par  . Licence CC By‑SA.
Étiquettes :
1
23
déc.
2013

Bonjour.

Je cherche à obtenir le "device file" correspondant à un chemin (sur une clé USB, en l'occurrence).

Disons que mon chemin est /media/cle/rep1/rep2/rep3/fichier. (J'ai accès à ça facilement dans Thunar via les actions personnalisées.)

Je veux :

  • extraire /media/cle
  • chercher ça dans /proc/mounts
  • en déduire /dev/sdb1 (par exemple)

Partant de /media/cle, je peux réaliser les étapes 2 et 3 avec awk :

awk '/\/media\/cle/ {print $1}' /proc/mounts

J'arrive à extraire /media/cle avec sed :

echo /media/cle/rep1/rep2/rep3/fichier | sed -e "s#\(/[^/]*/[^/]*\).*#\1#"

(Je n'ai pas réussi à utiliser {2} donc j'ai mis deux fois /[/]*)

Je peux remplacer les / par des \/ pour awk.

echo /media/cle/rep1/rep2/rep3/fichier |  sed -e "s#\(/[^/]*/[^/]*\).*#\1#" | sed "s#\/#\\\/#g"

Mais je ne parviens pas à utiliser la sortie de sed comme chaîne à rechercher par awk.

Si j'utilise l'accent grave, ça fait râler awk.

awk '/`echo /media/cle/rep1/rep2/rep3/fichier | sed -e "s#\(/[^/]*/[^/]*\).*#\1#" | sed "s#\/#\\\/#g"`/ {print $1}' /proc/mounts

awk: line 1: syntax error at or near sed
awk: line 1: runaway regular expression / {print $1 ...

Ma question est donc, plus largement, comment utiliser la sortie d'une commande comme chaîne de recherche de awk.

Bien sûr, s'il y a une façon plus simple de faire ce que je veux faire, ça m'intéresse aussi. J'ai très peu de théorie, que ce soit avec sed, awk ou les expressions régulières (je suppose que ça se voit…), donc je fonctionne en essai/erreur.

Merci.

  • # awk -F'X'

    Posté par  . Évalué à 3.

    l'option -F permet à awk d'utiliser un autre separateur que l'espace habituel.

    awk -F'/' '{print $2" "$3} '

    permet de prendre / comme separateur et de recuperer les colonnes 2 et 3 pour les afficher separees par un espace.

    awk -F'/' '{print "/"$2"/"$3} '

    permet donc de decouper sur les / et d'afficher la deuxieme (media) et 3e colonne (cle)
    avec un / devant et un / entre les deux

    • [^] # Re: awk -F'X'

      Posté par  . Évalué à 2.

      cut permet aussi de spécifier le délimiteur de champs:

      cut -d '/' -f 1,3
      • [^] # Re: awk -F'X'

        Posté par  . Évalué à 2.

        sauf que la question etait

        chaîne de recherche de awk

        mais comme il ne precisait pas la commande entrante, ca reste valable.

        avec cut, tu peux "reecrire" la chaine pour obtenir /1/2 en sortie ?

        • [^] # Re: awk -F'X'

          Posté par  . Évalué à 3.

          chaîne de recherche awk

          Certes, mais il y avait aussi du sed dans la question, alors du coup … ;-)
          non, en vrai, il y a deux raisons :

          • le demandeur ajoute parfois une contrainte technologique par ignorance des alternatives plutôt que par choix délibéré de la techno vraiment adaptée à son problème,
          • je ne suis pas super fan de awk, et je crois qu'on peut le remplacer par quelque chose de "mieux" (souvent sed) dans quasiment tous les cas.

          avec cut, tu peux "reecrire" la chaine pour obtenir /1/2 en sortie ?

          j'imagine que tu pensais /2/1 ?
          Si c'est bien le cas, la réponse est, à ma connaissance, non, mais il se trouve que ce n'était pas la question ! ;-)
          Pour extraire des champs sans réordonner -> cut, pour des trucs hors périmètre de cut -> autre chose

          • [^] # Re: awk -F'X'

            Posté par  . Évalué à 2.

            sauf que dans son exemple il veut sortir /media/cle de la chaine /media/cle/chemin/vers/fichier

            donc en plus de sortir les mots media et cle il faut remettre les /

            • [^] # Re: awk -F'X'

              Posté par  . Évalué à 2.

              hmmm … alors j'avais mal compris ta question … et je pensais que t'avais testé la version avec cut :D

              cut utilise aussi les délimiteurs dans la sortie, donc, pas besoin de les remettre, ils y sont déjà.

  • # df

    Posté par  . Évalué à 6. Dernière modification le 23 décembre 2013 à 23:19.

    La commande df fait le lien entre le chemin et le système de fichier, par exemple :

    $ df /home/bob/.config/awesome/rc.lua
    Filesystem     1K-blocks      Used Available Use% Mounted on
    /dev/sda4      123123123  51711712  71411411  42% /home
    • [^] # Re: df

      Posté par  . Évalué à 2.

      Bien vu. Alors ceci devrait fonctionner :

      df /media/cle/rep1/rep2/rep3/fichier | sed 1d | sed "s/ .*//"
      

      Le premier sed vire les en-tête de df, le second vire tout dès le premier espace.

      Merci aux autres pour les réponses, que j'étudierai pour la culture.

      Pour info, le but est de pouvoir lancer fatsort depuis n'importe quel répertoire de ma clé USB.

      http://linuxfr.org/users/jihele/journaux/fatsort-a-la-rescousse-des-autoradios-mp3

      (Certes, la clé est montée, il faut faire fatsort -f et c'est pas top, mais c'est une autre histoire.)

      J'ai déjà une action personnalisée pour ça mais elle m'obligeait à être sur le répertoire de montage, ce qui est moins pratique.

      Ça devrait donc marcher avec ça :

      fatsort -f `df /media/cle/rep1/rep2/rep3/fichier | sed 1d | sed "s/ .*//"`
      

      Merci !

      • [^] # Re: df

        Posté par  . Évalué à 3.

        Note que tu invoques sed une fois de trop, tu peux écrire

        sed "1d; s/ .*//"

        ça n'a l'air de rien, mais sur des gros volumes de données, la différence en performance peut-être significative

  • # | getline

    Posté par  (site web personnel) . Évalué à 4.

    Ma question est donc, plus largement, comment utiliser la sortie d'une commande comme chaîne de recherche de awk.

    BEGIN {
        "echo truc" | getline; # met la sortie dans $0
        if ( "biduletrucchosemachin" ~ $0 ".*machin") {
                print "matches\n";
        }
    }

    Pour getline c'est expliqué ici. Pour matcher, tu peux soit utiliser une regexp constante entre /.../ qui se fait à la compilation (donc tu peux pas interpoler), soit une chaîne de caractère quelconque comme ici qui se compile en expression régulière à l'éxécution. C'est expliqué .

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.