Используйте bash для извлечения числа из квадратных скобок

Мой файл выглядит так:

[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);

Каждая новая строка начинается с шаблона [number]. Каждая строка заканчивается шаблоном );.

Мне нужно извлечь числа в квадратных скобках из начала каждой строки и записать их в новый файл. Я не знаю, сколько строк в файле есть заранее.

3
задан 21 May 2015 в 22:58

6 ответов

Можно достигнуть этого только с синглом grep команда. Это вызвано тем, что GNU grep позволяет Вам использовать регулярное выражение Perl (-P), который поддерживает нулевую ширину lookaround утверждения (\K и (?= ), в этом случае):

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

Как записано, это отправит вывод на Ваш терминал. Для перенаправления его в файл используйте:

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

Этот метод имеет преимущество краткости и простоты. Это соответствует тексту это

  • предшествуется (\K)

    • a [ символ (\[) -- \ необходим как [ иначе имеет особое значение в регулярных выражениях
    • это появляется в начале строки (^);
  • состоит из одного или нескольких (+) цифры (\d);

  • сопровождается ((?= ))

    • a ] символ (\]) - как с [, \ силы ] быть согласованным буквально.
12
ответ дан 21 May 2015 в 22:58

Используя sed:

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

Разбивка команды:

  • < inputfile: перенаправляет содержание inputfile кому: stdin
  • -n: подавляет вывод
  • > out: перенаправляет содержание stdout кому: out

Разбивка Regex:

  • s: выполняет замену
  • /: запускает regex
  • ^: соответствует запуску строки
  • \[: соответствия a [ символ
  • \(: запускает группу фиксации
  • [0-9]*: соответствия любое количество цифр
  • \): останавливает группу фиксации
  • \]: соответствия a ] символ
  • .*: соответствия любое количество любого символа
  • $: соответствует концу строки
  • /: останавливается regex / запускает замену
  • \1: замены первой группой фиксации
  • /: останавливает замену
  • p: печать только согласующие отрезки длинной линии

Используя grep+tr (если Вам нужен метод, который работает и на Ubuntu и на другой ОС чей grep не поддерживает PCRE - иначе, относятся к Eliah Kagan grep- только версия):

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

Разбивка команды:

  • < inputfile в grep: перенаправляет содержание inputfile кому: stdin
  • -o в grep: печать только соответствие
  • -d в tr: удаляет символы
  • > out в tr: перенаправляет содержание stdout кому: out

Разбивка Regex:

  • ^: соответствует запуску строки
  • \[: соответствия a [ символ
  • [0-9]*: соответствия любое количество цифр
  • \]: соответствия a ] символ
7
ответ дан 21 May 2015 в 22:58

perl путь:

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

или с awk:

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

Используемый Regex в обоих случаях:

^\[[0-9]*\]

Объяснение

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

    • ^ утверждайте положение в начале строки

    • \[ соответствует символу [ буквально

    • [0-9]* соответствуйте отдельному символу, существующему в списке ниже

      • Квантор: * Между нулевыми и неограниченными временами, максимально много раз, отдавая по мере необходимости [жадный]

      • 0-9 отдельный символ в диапазоне между 0 и 9

    • \] соответствует символу ] буквально

    Regular expression visualization
    (источник: debuggex.com)

    Демонстрация Debuggex

3
ответ дан 21 May 2015 в 22:58

Используйте это в Bash:

 grep -oh '\[[0-9].*\]' mytestfile | sed 's/.*\[\([^]]*\)\].*/\1/g' > myresultfile
0
ответ дан 21 May 2015 в 22:58

python решение с помощью re модуль и рассматривая две ситуации:

#!/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()

Вывод:

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

Здесь я рассмотрел две ситуации, поскольку Ваш вопрос не кажется ясным мне.

  • digits_case_1 распечатает соответствие цифр между [] в начале строки, оно не рассмотрит, заканчивается ли строка ); или нет.

  • digits_case_2 распечатает цифры между [] в начале строки, только если строка заканчивается );.

0
ответ дан 21 May 2015 в 22:58

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

, Где прогрессия: <глоток> В§

$ 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

$

<глоток> В§ Для тех без доступа к эти man команда.

0
ответ дан 21 May 2015 в 22:58

Другие вопросы по тегам:

Похожие вопросы: