Извлечение чисел от текстовых файлов

У меня есть некоторые текстовые файлы, из которых я хочу извлечь определенные данные. Я хочу извлечь некоторые определенные числа от них. В особенности я хочу искать файлы первое вхождение string1 и возьмите числа, которые следуют за ним. Таким образом, я хочу взять все числа, точки или знаки "минус" и остановиться, после того как другой символ достигнут. Затем я хочу послать запрос те числа в отдельный файл.

Предпочтительно я смог бы сделать это для нескольких строк сразу (так также ищите string2, сделайте то же там и пошлите запрос результаты в некотором перечисленном формате, скажите {numbers1,numbers2}. Но эта последняя часть менее важна.

Как я выполнил бы это?


Я не включал определенные данные, так как надеялся, что было общее решение для вопроса, который я задал. Такой инструмент был бы обычно полезен в многочисленных случаях. (Я пытался соединить общее решение от различных вопросов о том, как извлечь число из определенной строки, но отказавший.)

Данные посмотрели бы что-то как

bla bla bla label1_5234_blablab_some_other_text_and_numbers_23343_blabla_more_text_and_numbers_maybe_label1_again_but_now_I_no_longer_care_about_what_comes_after blabla_label2_34343_this_is_some_other_number_want_to_be_able_to_extract_if_I_look_for_label2_instead_of_label1
label3 = -0.34343 
and_more_text_and_so_on_and_so_forth

Шаблоны для поиска затем были бы label1_, label2_ или label3 =. (Конечно, это должно работать независимо от точной формы label1. Но так как это, по-видимому, не было абсолютно ясно, позволяют мне добавить другой пример. height_2.3 blabla_bla_length_3.4, должен дать 2.3, 3.4 или {2.3,3.4} в зависимости от того, просим ли мы высоту, длину или обоих.)

И вывод был бы, если дали один шаблон, чтобы искать, сказать label1_

5234

или при поиске label3 =

-0.34343

Затем, кроме того, было бы хорошо, если это могло бы искать две вещи сразу и сгруппировать их. Так, например, предоставление обоих шаблонов выше вывода

{5234,-0.34343}

Наконец было бы хорошо, если это могло бы сгруппировать результаты для этого для нескольких файлов, если питается несколько файлов:

{out1a,out1b}
{out2a,out2b}
3
задан 18 February 2019 в 06:01

3 ответа

Если Вы хотите все результаты единственного группировавшегося файла, то является, вероятно, самым легким хлебать весь каждый файл в память и обработать его как один блок. Можно выполнить в этом perl путем сбрасывания разделителя строки - стандартный способ сделать это в остроте жемчуга -0777.

Затем Вам нужно регулярное выражение, которое соответствует последовательности десятичных цифр, десятичные разделители, которым и т.д. предшествуют label[123]_ или label[123] =

Соединение его:

perl -0777nE 'say "{", (join ",", /label[123](?:_| = )\K[0-9.+-]+/g), "}"' file1 file2 [...]

Примечание: Я не попытался обратиться maybe_label1_again_but_now_I_no_longer_care_about_what_comes_after

2
ответ дан 17 November 2019 в 09:37

sed решение

С $p содержание маркировки regex, например. p='label[13](_\| = )':

sed ':a;N;$!ba;s/\n/ /g;s/'"$p"'[-.0-9]\+/&\n/g' | \
sed '/.*'"$p"'[-.0-9]\+/!d;s/.*'"$p"'\([-.0-9]\+\)/\2/' | \
sed ':a;N;$!ba;s/\n/,/g;s/.*/{&}/'

Первая команда удаляет разрывы строки и добавляет новый после того, как каждое соответствие, второе удаляет строки без соответствия и извлекает числа, и третий делает их разделенными от запятой и включает их в фигурные скобки.

$p должен содержать допустимый regex и точно одну группу (или необходимо скорректировать часть RHS третьего выражения замены), например:

p='label1\(_\)'
p='label3\( = \)'
p='label[13]\(_\| = \)'
p='\(label1_\|label3 = \)'
p='\(height\|length\)_'

Несколько различных строк в группе должны быть разделены \|.

Примеры

$ <input cat
bla bla bla label1_5234_blablab_some_other_text_and_numbers_23343_blabla_more_text_and_numbers_maybe_label1_again_but_now_I_no_longer_care_about_what_comes_after blabla_label2_34343_this_is_some_other_number_want_to_be_able_to_extract_if_I_look_for_label2_instead_of_label1
label3 = -0.34343 
and_more_text_and_so_on_and_so_forth
$ p='label1\(_\)'
$ <input sed ':a;N;$!ba;s/\n/ /g;s/'"$p"'[-.0-9]\+/&\n/g' | sed '/.*'"$p"'[-.0-9]\+/!d;s/.*'"$p"'\([-.0-9]\+\)/\2/' | sed ':a;N;$!ba;s/\n/,/g;s/.*/{&}/'
5234
$ p='label3\( = \)'
$ <input sed ':a;N;$!ba;s/\n/ /g;s/'"$p"'[-.0-9]\+/&\n/g' | sed '/.*'"$p"'[-.0-9]\+/!d;s/.*'"$p"'\([-.0-9]\+\)/\2/' | sed ':a;N;$!ba;s/\n/,/g;s/.*/{&}/'
-0.34343
$ p='label[13]\(_\| = \)'
$ <input sed ':a;N;$!ba;s/\n/ /g;s/'"$p"'[-.0-9]\+/&\n/g' | sed '/.*'"$p"'[-.0-9]\+/!d;s/.*'"$p"'\([-.0-9]\+\)/\2/' | sed ':a;N;$!ba;s/\n/,/g;s/.*/{&}/'
{5234,-0.34343}
$ echo "height_2.3 blabla_bla_length_3.4" >>input
$ p='\(height\)_'
$ <input2 sed ':a;N;$!ba;s/\n/ /g;s/'"$p"'[-.0-9]\+/&\n/g' | sed '/.*'"$p"'[-.0-9]\+/!d;s/.*'"$p"'\([-.0-9]\+\)/\2/' | sed ':a;N;$!ba;s/\n/,/g;s/.*/{&}/'
2.3
$ p='\(height\|length\)_'
$ <input2 sed ':a;N;$!ba;s/\n/ /g;s/'"$p"'[-.0-9]\+/&\n/g' | sed '/.*'"$p"'[-.0-9]\+/!d;s/.*'"$p"'\([-.0-9]\+\)/\2/' | sed ':a;N;$!ba;s/\n/,/g;s/.*/{&}/'
{2.3,3.4}
2
ответ дан 17 November 2019 в 09:37

Для единственного файла

grep -oP "(?<=label1_)[0-9.+-]+[^_ ]+" ./file | head -n 1 >> ./tmpfile
grep -oP "(?<=label3 = )[0-9.+-]+[^_ ]+" ./file | head -n 1 >> ./tmpfile
paste -sd, ./tmpfile | awk '{ print "{"$0"}" }' >> ./newfile
rm ./tmpfile

Для нескольких файлов в папке.
CD к папке и выполненный:

for file in *; do
if [ "$file" == "newfile" ] ; then continue; fi
grep -oP "(?<=label1_)[0-9.+-]+[^_ ]+" $file | head -n 1 >> ./tmpfile
grep -oP "(?<=label3 = )[0-9.+-]+[^_ ]+" $file | head -n 1 >> ./tmpfile
paste -sd, ./tmpfile | awk '{ print "{"$0"}" }' >> ./newfile
rm ./tmpfile
done
2
ответ дан 17 November 2019 в 09:37

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

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