Мой файл выглядит так:
[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]
. Каждая строка заканчивается шаблоном );
.
Мне нужно извлечь числа в квадратных скобках из начала каждой строки и записать их в новый файл. Я не знаю, сколько строк в файле есть заранее.
Можно достигнуть этого только с синглом grep
команда. Это вызвано тем, что GNU grep позволяет Вам использовать регулярное выражение Perl (-P
), который поддерживает нулевую ширину lookaround утверждения (\K
и (?=
)
, в этом случае):
grep -oP '^\[\K\d+(?=\])' infile
Как записано, это отправит вывод на Ваш терминал. Для перенаправления его в файл используйте:
grep -oP '^\[\K\d+(?=\])' infile > outfile
Этот метод имеет преимущество краткости и простоты. Это соответствует тексту это
предшествуется (\K
)
[
символ (\[
) -- \
необходим как [
иначе имеет особое значение в регулярных выражениях^
);состоит из одного или нескольких (+
) цифры (\d
);
сопровождается ((?=
)
)
]
символ (\]
) - как с [
, \
силы ]
быть согласованным буквально.Используя 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 ]
символ 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
\]
соответствует символу ]
буквально
(источник: debuggex.com)
Используйте это в Bash:
grep -oh '\[[0-9].*\]' mytestfile | sed 's/.*\[\([^]]*\)\].*/\1/g' > myresultfile
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
распечатает цифры между []
в начале строки, только если строка заканчивается );
.
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
команда.