web-dev-qa-db-fra.com

Utilisez bash pour extraire le nombre entre crochets

Mon fichier ressemble à ceci:

[581]((((((((501:0.00024264,451:0.00024264):0.000316197,310:0.000558837):0.00857295,((589:0.000409158,538:0.000409158):0.000658084,207:0.00106724
):0.00806454):0.0429702,(((198:0.00390205,91:0.00390205):0.016191,79:0.0200931):0.0147515,(187:0.00133008,50:0.00133008):0.0335145):0.0172574):0.
127506,((140:0.00253019,117:0.00253019):0.0533693,(((533:0.00728707,(463:8.80494e-05,450:8.80494e-05):0.00719902):0.0217722,389:0.0290593):0.0253
931,(((141:0.018004,107:0.018004):0.0143861,(111:0.00396127,(106:0.00161229,12:0.00161229):0.00234898):0.0284289):0.0145736,(129:0.0195982,((123:
0.0105973,66:0.0105973):0.0084867,10:0.019084):0.000514243):0.0273656):0.00748854):0.00144709):0.123708):0.000944439,((181:0.00108761,71:0.00108761):0.0819772);  
[50]((((((((501:0.00024264,451:0.00024264):0.000316197,310:0.000558837):0.00857295,((589:0.000409158,538:0.000409158):0.000658084,207:0.00106724):0.00806454):0.0429702,(((198:0.00390205,91:0.00390205):0.016191,79:0.0200931):0.0147515,(187:0.00133008,50:0.00133008):0.0335145):0.0172574):0.127506,((140:0.00253019,117:0.00253019):0.0533693,(((533:0.00728707,(463:8.80494e-05,450:8.80494e-05):0.00719902):0.0217722,389:0.0290593):0.0253931,(((141:0.018004,107:0.018004):0.0143861,(111:0.00396127,(106:0.00161229,12:0.00161229):0.00234898):0.0284289):0.0145736,(129:0.0195982,((123:0.0105973,66:0.0105973):0.0084867,10:0.019084):0.000514243):0.0273656):0.00748854):0.00144709):0.123708):0.000944439,((181:0.00108761,71:0.00108761):0.0819772);

Chaque nouvelle ligne commence par le motif [number]. Chaque ligne se termine par le motif );.

Je dois extraire les nombres entre crochets à partir du début de chaque ligne et les écrire dans un nouveau fichier. Je ne sais pas combien de lignes le fichier a au préalable.

3
user3069326

Vous pouvez y parvenir avec une seule commande grep . Ceci est dû au fait que GNU grep vous permet d’utiliser une expression régulière Perl (-P), qui prend en charge assertions de zone de largeur nulle (\K et (?=), dans ce cas):

grep -oP '^\[\K\d+(?=\])' infile

Comme écrit, cela enverra la sortie à votre terminal. Pour le rediriger vers un fichier, utilisez:

grep -oP '^\[\K\d+(?=\])' infile > outfile

Cette méthode a l'avantage de la brièveté et de la simplicité. Cela correspond au texte qui

  • est précédé de (\K)

    • un [ caractère (\[) - \ est requis car [ a autrement une signification spéciale dans les expressions régulières
    • qui apparaît au début d'une ligne (^);
  • consiste en un ou plusieurs (+) chiffres (\d);

  • est suivi de ((?=))

    • un ] caractère (\]) - comme avec [, \ oblige ] à correspondre de manière littérale.
12
Eliah Kagan

Utiliser sed:

  • < inputfile sed -n 's/^\[\([0-9]*\)\].*$/\1/p' > out

Répartition des commandes :

  • < inputfile: redirige le contenu de inputfile vers stdin
  • -n: supprime la sortie
  • > out: redirige le contenu de stdout vers out

Répartition des regex :

  • s: effectue une substitution
  • /: lance la regex
  • ^: correspond au début de la ligne
  • \[: correspond à un caractère [
  • \(: démarre le groupe de capture
  • [0-9]*: correspond à un nombre quelconque de chiffres
  • \): arrête le groupe de capture
  • \]: correspond à un caractère ]
  • .*: correspond à un nombre quelconque de caractères
  • $: correspond à la fin de la ligne
  • /: arrête la regex/démarre le remplacement
  • \1: remplace par le premier groupe de capture
  • /: arrête le remplacement
  • p: imprime uniquement les lignes correspondantes

Utilisation de grep + tr (si vous avez besoin d’une méthode fonctionnant à la fois sous Ubuntu et sur un autre système d’exploitation dont grep ne prend pas en charge PCRE - sinon, reportez-vous à Eliah Kagan grep- version seulement ):

  • < inputfile grep -o '^\[[0-9]*\]' | tr -d '[]' > out

Répartition des commandes :

  • < inputfile dans grep: redirige le contenu de inputfile vers stdin
  • -o in grep: imprime uniquement la correspondance
  • -d dans tr: supprime les caractères
  • > out dans tr: redirige le contenu de stdout vers out

Répartition des regex :

  • ^: correspond au début de la ligne
  • \[: correspond à un caractère [
  • [0-9]*: correspond à un nombre quelconque de chiffres
  • \]: correspond à un caractère ]
7
kos

la manière Perl:

Perl -ne 'print "$1\n" if /^\[([0-9]*)\].*/' testdata > out

ou avec awk:

awk 'match($0, /^\[[0-9]*\]/) {print substr($0, RSTART + 1, RLENGTH - 2)}' testdata > out

Regex utilisé dans les deux cas:

^\[[0-9]*\]

Explication

  • /^\[[0-9]*\]/

    • ^ assert la position au début de la chaîne

    • \[ correspond au caractère [ littéralement

    • [0-9]* correspond à un seul caractère présent dans la liste ci-dessous

      • Quantificateur: * Entre zéro et un nombre illimité de fois, autant de fois que possible, redonner au besoin [gourmand]

      • 0-9 un seul caractère compris entre 0 et 9

    • \] correspond au caractère ] littéralement

    Regular expression visualization
    (source: debuggex.com )

    Démo Debuggex

3
A.B.

Utilisez ceci dans Bash:

 grep -oh '\[[0-9].*\]' mytestfile | sed 's/.*\[\([^]]*\)\].*/\1/g' > myresultfile
2
Frantique

python solution utilisant le module re et considérant deux situations:

#!/usr/bin/env python2
import re
with open('/path/to/file.txt') as f:
    for line in f:
        digits_case_1 = re.search(r'(?<=^\[)\d+(?=\])', line)
        digits_case_2 = re.search(r'(?<=^\[)\d+(?=\].*\);$)', line)
        if digits_case_1:
            print 'Not considering ");" at end: ' + digits_case_1.group()
        if digits_case_2:
            print 'Considering ");" at end: ' + digits_case_2.group()

Sortie:

Not considering ");" at end: 581
Not considering ");" at end: 50
Considering ");" at end: 50

Ici, j'ai considéré deux situations, car votre question ne me semble pas claire.

  • digits_case_1 imprimera la correspondance de chiffres entre [] au début de la ligne. Il ne sera pas tenu compte du fait que la ligne se termine par ); ou non.

  • digits_case_2 imprimera les chiffres entre [] au début de la ligne uniquement si celle-ci se termine par );.

1
heemayl

cat $FILE | awk -F\] '{ print $1 }' | grep '\[' | tr -d '['

Où la progression est:§

$ FILE=/tmp/tmp.tmp

$ cat $FILE
[581]((((((((501:0.00024264,451:0.00024264):0.000316197,310:0.000558837):0.00857295,((589:0.000409158,538:0.000409158):0.000658084,207:0.00106724
):0.00806454):0.0429702,(((198:0.00390205,91:0.00390205):0.016191,79:0.0200931):0.0147515,(187:0.00133008,50:0.00133008):0.0335145):0.0172574):0.
127506,((140:0.00253019,117:0.00253019):0.0533693,(((533:0.00728707,(463:8.80494e-05,450:8.80494e-05):0.00719902):0.0217722,389:0.0290593):0.0253
931,(((141:0.018004,107:0.018004):0.0143861,(111:0.00396127,(106:0.00161229,12:0.00161229):0.00234898):0.0284289):0.0145736,(129:0.0195982,((123:
0.0105973,66:0.0105973):0.0084867,10:0.019084):0.000514243):0.0273656):0.00748854):0.00144709):0.123708):0.000944439,((181:0.00108761,71:0.00108761):0.0819772);
[50]((((((((501:0.00024264,451:0.00024264):0.000316197,310:0.000558837):0.00857295,((589:0.000409158,538:0.000409158):0.000658084,207:0.00106724):0.00806454):0.0429702,(((198:0.00390205,91:0.00390205):0.016191,79:0.0200931):0.0147515,(187:0.00133008,50:0.00133008):0.0335145):0.0172574):0.127506,((140:0.00253019,117:0.00253019):0.0533693,(((533:0.00728707,(463:8.80494e-05,450:8.80494e-05):0.00719902):0.0217722,389:0.0290593):0.0253931,(((141:0.018004,107:0.018004):0.0143861,(111:0.00396127,(106:0.00161229,12:0.00161229):0.00234898):0.0284289):0.0145736,(129:0.0195982,((123:0.0105973,66:0.0105973):0.0084867,10:0.019084):0.000514243):0.0273656):0.00748854):0.00144709):0.123708):0.000944439,((181:0.00108761,71:0.00108761):0.0819772);

$ cat $FILE | awk -F\] '{ print $1 }'
[581
):0.00806454):0.0429702,(((198:0.00390205,91:0.00390205):0.016191,79:0.0200931):0.0147515,(187:0.00133008,50:0.00133008):0.0335145):0.0172574):0.
127506,((140:0.00253019,117:0.00253019):0.0533693,(((533:0.00728707,(463:8.80494e-05,450:8.80494e-05):0.00719902):0.0217722,389:0.0290593):0.0253
931,(((141:0.018004,107:0.018004):0.0143861,(111:0.00396127,(106:0.00161229,12:0.00161229):0.00234898):0.0284289):0.0145736,(129:0.0195982,((123:
0.0105973,66:0.0105973):0.0084867,10:0.019084):0.000514243):0.0273656):0.00748854):0.00144709):0.123708):0.000944439,((181:0.00108761,71:0.00108761):0.0819772);
[50

$ cat $FILE | awk -F\] '{ print $1 }' | grep '\['
[581
[50

$ cat $FILE | awk -F\] '{ print $1 }' | grep '\[' | tr -d '['
581
50

$

§ Pour ceux qui n'ont pas accès à la commande man.

0
boardrider