Как извлечь числа из строки и вывести их в виде значений через запятую? - PullRequest
2 голосов
/ 30 мая 2019

У меня есть test_file в bash, который выводит следующее на экране.У меня нет контроля над исходным кодом, чтобы печатать их определенным образом.Итак, мне нужно разобрать некоторые значения из вывода на экран.Вот что я делаю:

MyOut=$(./my_test_file.sh)    # this is my example script which echo's the 
                                 #output
echo $MyOut    

показывает мне следующее

output for different segments IP address: 192.168.0.12 Segment :0xfff Segment Data: 123 23 42 23 4 444 1121 8676 34 530 323 564 523 7878 7328 96

мои ожидаемые результаты будут строковой переменной

123,23,42,23,4,444,1121,8676,34,530,323,564,523,7878,7328,96

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

Я попытался поиграть с регулярными выражениями и хотел бы извлечь только последние 16 чисел в следующем выводе

Я сделал это

numbers=$(echo $MyOut | grep -o -E '[0-9]+')

дает мне

192 168 0 12 0 123 23 42 23 4 444 1121 8676 34 530 323 564 523 7878 7328 96

Мне нужно извлечь последние 16 чисел.Так как это не формат массива, могу ли я добавить в регулярное выражение что-то, что только выплевывает только последние 16 чисел, разделенных запятой ???

Кстати, если вам нужно заглянуть в my_test_file.sh, он просто повторяет утверждения

#!/bin/bash

echo "output for different segments "
echo "IP address: 192.168.0.12 Segment :0xfff"                        
echo "Segment Data:"                                                                 
echo "123"                                                                            
echo "23"                                                                          
echo "42"                                                                           
echo "23"                                                                           
echo "4"                                                                           
echo "444"                                                                           
echo "1121"                                                                           
echo "8676"                                                                           
echo "34"                                                                           
echo "530"                                                                           
echo "323"                                                                           
echo "564"                                                                           
echo "523"                                                                            
echo "7878"                                                                            
echo "7328"                                                                            
echo "96"

Спасибо, Эш

Ответы [ 5 ]

1 голос
/ 30 мая 2019
MyOut=$(./my_test_file.sh | tail -n +4 | paste -sd ",")

tail -n +4 перейдет к 4-й строке вашего вывода, а paste объединит строки запятой вместо пробела.

В комментариях вы упоминаете, что у вас нет доступа к paste - а как насчет tr?

MyOut=$(./my_test_file.sh | tail -n +4 | tr '\n' ',')
0 голосов
/ 31 мая 2019

Попробуйте это Shellcheck - чистый чистый код Bash:

#! /bin/bash -p

myout=$(./my_test_file.sh)
read -r -d '' -a parts <<<"$myout"
numlist=${parts[*]: -16}
result=${numlist// /,}

printf '%s\n' "$result"
  • Используя my_test_file.sh, указанный в вопросе, он печатает 123,23,42,23,4,444,1121,8676,34,530,323,564,523,7878,7328,96.
  • Код предполагает, что IFS имеет значение по умолчанию.
  • read помещает разделенные пробелами части значения myout в массив parts. -d '' заставляет read продолжаться через новые строки (в противном случае он остановится после прочтения первой строки) Опция -r отключает странную обработку обратной косой черты во входных данных (что не должно иметь значения, но это наиболее безопасно для * 1021). * всегда используйте -r с read, а Shellcheck выдаст предупреждение, если оно отсутствует).
  • numlist=${parts[*]: -16} устанавливает строку numlist для последних 16 элементов массива parts, разделенных первым символом $IFS (по умолчанию пробел).
  • result=${numlist// /,} устанавливает result в значение numlist, все пробелы заменяются запятыми.
0 голосов
/ 30 мая 2019

Использование только awk:

./my_test_file.sh |awk -vlast=16 -v RS=    '{gsub(/[^[:digit:]]/," ") ; for(i=NF-last+1;i<=NF;i++) if(i!=NF)printf $i",";else print $i}'
123,23,42,23,4,444,1121,8676,34,530,323,564,523,7878,7328,96

Впервые использовалась функция gsub() для удаления всех нецифровых символов из каждой строки, а затем повторяется для последних 16 столбцов.printf и print оба используются для работы с последней запятой.

0 голосов
/ 30 мая 2019

Другой способ:

echo "output for different segments IP address: 192.168.0.12 Segment :0xfff Segment Data: 123 23 42 23 4 444 1121 8676 34 530 323 564 523 7878 7328 96" | awk -F'Segment Data: ' '{print $2}' | sed 's/ /,/g'

дает вам:

123,23,42,23,4,444,1121,8676,34,530,323,564,523,7878,7328,96
0 голосов
/ 30 мая 2019

вот пример сценария awk:

 text="output for different segments IP address: 192.168.0.12 Segment :0xfff Segment Data: 123 23 42 23 4 444 1121 8676 34 530 323 564 523 7878 7328 96"
 echo $text |awk '{sub(/^.*Segment Data: /,"");gsub(/ /,",")}1' 

выход:

123,23,42,23,4,444,1121,8676,34,530,323,564,523,7878,7328,96

explantion:

sub(/^.*Segment Data: /,"") удалить текст с начала строки до Segment Data:

gsub(/ /,",") заменить все на ,

1 печать измененной строки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...