Подстрока чисел из строки не Ascii в bash - PullRequest
0 голосов
/ 24 мая 2018

У меня есть строка, которая читается из файла, и она содержит все типы символов, отличных от ascii, например:

line=^AÀÀ^P^G^P^@^H15552655^@^@E$4c<84>%ÿ~^@^@^Ac<8f>/qu^Q»í&.WÈå

Теперь мне просто нужно извлечь из этого числа '15552655'.

Что я пробовал:

line=$(sed -n '1p' < file)

number=$(echo "${line//[!0-9]/}")
              or
number=$(echo $line | sed 's/[^0-9]*//g')

Но это возвращает '155526554', поэтому мне нужен способ извлечь подстроку из строки, которая непрерывно содержит как минимум 4 последовательных числа [Гарантировано, что будет по крайней мере 4числа в этом шаблоне]

Любая помощь будет принята с благодарностью.

Update-1:

number=$(echo $line | sed 's/[^0-9]*\([0-9]\{1,\}\).*$/\1/')

Кажется, что это работает для вышеупомянутого случая, но это не удастся, есливход имеет такой формат

line=^AÀÀ^P^4G^P^@^H15552655^@^@E$4c<84>%ÿ~^@^@^Ac<8f>/qu^Q»í&.WÈå

В этом случае он возвращает 4, т.е. он возвращает первый цикл чисел.Мне нужно добавить что-то, что говорит, дайте мне самое длинное или более 4 цифр.

Ответы [ 4 ]

0 голосов
/ 24 мая 2018

Как насчет этого:

number=$(echo "$line" | tr -cs '0-9' '\n' | awk '{if (length>l) { n=$0; l=length }} END { print n }')

Объяснение: Двойные кавычки вокруг $line не позволяют оболочке делать что-то странное, если строка содержит определенные метасимволы оболочки.tr -cs '0-9' '\n' заменяет все, что не является цифрой, символами новой строки, «сжимая» вместе серии замененных символов;по сути, это создает список чисел в файле, по одному на строку.Затем в awk {if (length>l) { n=$0; l=length }} говорит, что для каждой входной строки, если ее length длиннее, чем она видела ранее (l), установите n для текущей строки и l для ее длины.Часть END { print n } заставляет печатать самую длинную строку, когда она достигает конца ввода.

0 голосов
/ 24 мая 2018

Я бы использовал head и grep:

head -1 filename | grep -o '[0-9]\{4,\}'

Здесь [0-9]\{4,\} соответствует любой серии из четырех или более цифр.Переключатель -o указывает grep печатать только эти совпадения (в отдельной строке).

Если это все еще дает ложные срабатывания, вы можете обработать их дальше, чтобы найти наибольшее число в связкеиспользуя sort и tail, как в

head -1 filename | grep -o '[0-9]\{4,\}' | sort -n | tail -1

Это в свою очередь:

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

Если символ «H» является префиксом перед номером, вы можете использовать его для предотвращения получения правильного номера.

#!/bin/bash

line="^AÀÀ^P1^G88^P^@^H15552655^@^@E$4c<84>%ÿ~^@^@^Ac<8f>/qu^Q»í&.WÈå"
echo -e "line="$line"\n"

strA=$(   echo $line | sed -E 's/.*H([0-9]+).*/\1/g'   )
strB=$(   echo $line | sed -n 's/[^0-9]*\([0-9]\+\).*/\1/p'  )
strC=$(   echo $line | sed -E 's/.*\^H([0-9]+)\^.*/\1/g'   )
strD=$(   echo $line | sed -E 's/(.*)([0-9]{8})(.*)/\2/g'   )    # without 'H' prefix

echo $strA    # 15552655
echo $strB    # 1
echo $strC    # 15552655
echo $strD    # 15552655

Но ваш вопрос дублирован!> sed извлекающая группа цифр

0 голосов
/ 24 мая 2018

Мое предложение состоит в том, чтобы разбить строку на числа, разделенные запятыми, а затем просмотреть эти цифры, чтобы удовлетворить ваши желания:

line="^AÀÀ^P^G^P^@^H15552655^@^@E$4c<84>%ÿ~^@^@^Ac<8f>/qu^Q»í&.WÈå"

number=$(echo $line | sed -E 's/[^0-9]+/,/g')
echo $number
==> ,15552655,84,8,

Найти самое длинное сложно.Вот одно из решений, но решение Гордона Дэвиссона является однострочным.

#!/bin/bash


line="^AÀÀ^P^G^P^@^H15552655^@^@E$4c<84>%ÿ~^@^@^Ac<8f>/qu^Q»í&.WÈå"

number=$(echo $line | sed -E 's/[^0-9]+/\\n/g')
max_length=0
this_index=0
saved_index=-1

echo $number | 
{ while read num ; do
pieces[$this_index]=$num
this_length=$(echo $num | wc -c | sed 's/ //g')
if [ $this_length -gt $max_length ]  ; then
    max_length=$this_length
    saved_index=$this_index
fi
this_index=$(expr $this_index + 1)
done


echo maxnum is ${pieces[$saved_index]}

}
...