Как напечатать самое длинное число в строке?
Я ищу метод для печати самого длинного числа в строке.
Например: если у меня есть строка
- sed в bash с переменными и двойными кавычками вызывает неисполненную ошибку
- как совместить все между строкой и перед следующим пространством
- Печать строк между двумя шаблонами с SED
- Удалить слово после матча
- захватить текст из файла vtt
212334123434test233
как я могу распечатать
212334123434
?
Примечание. Я ищу самую длинную непрерывную последовательность чисел, а не для более высокого значения.
Редактировать: Спасибо за ответы, всем. Ответ на этот вопрос был довольно подавляющим. Я отметил сообщение @ HaukeLaging в качестве принятого ответа, потому что он очень хорошо подходит для моего конкретного случая, но я хотел бы указать, что все ответы одинаково важны. Всегда здорово иметь несколько различных вариантов решения проблемы.
- Разбор C-стиля Многострочный комментарий
- Как эффективно выражать переменные для SED?
- Как сделать замену sed (s /// g) на основе списка? Мне нужно поменять несколько слов, с другими соответствующими словами
- Удаление следующего-последнего расширения в имени файла
- sed, конвертировать одиночную обратную косую черту в двойную обратную косую черту
- Как разобрать этот вывод и поместить его в массив?
- подсчитать все конкретные слова, которые заканчиваются в каждой строке
- sed заменяет только несколько регулярных выражений букв
9 Solutions collect form web for “Как напечатать самое длинное число в строке?”
echo 212334123434test233abc44 | awk '{gsub("[^0-9]+","\n"); print;}' | awk '{ if (length($0) > max) {max = length($0); maxline = $0} } END { print maxline }' 212334123434
Я считаю, что вы можете сделать это с помощью только grep
, sort
и tail
. Вот несколько примеров строк.
$ echo <str> | grep -oP "\d+" | sort -n | tail -1
Где <str>
– наша строка под вопросом.
пример
$ set -o posix; set | grep "str[0-9]" str0=212334123434test233 str1=212334123434test233abc44 str2=233test212334123434 str3=a212334123434test233abc44 str4=a91234b212334123434abc
Теперь, если я запустил их через мою команду grep ...
по очереди.
$ echo $str0 | grep -oP "\d+" | sort -n | tail -1 212334123434 $ echo $str1 | grep -oP "\d+" | sort -n | tail -1 212334123434 $ echo $str2 | grep -oP "\d+" | sort -n | tail -1 212334123434 $ echo $str3 | grep -oP "\d+" | sort -n | tail -1 212334123434 $ echo $str4 | grep -oP "\d+" | sort -n | tail -1 212334123434
Этот подход работает, выбирая все подстроки, которые являются последовательностями цифр. Затем мы сортируем этот результат численно, sort -n
, а затем берем последнее значение в списке, используя tail -1
. Это будет самая длинная подстрока.
Вы можете увидеть, как это работает, сняв tail -1
и повторив один из примеров:
$ echo $str4 | grep -oP "\d+" | sort -n 91234 212334123434
Строки, начинающиеся с нулей
Вышеупомянутый подход работает для любой ситуации, которую я мог бы представить, кроме одного. @terdon упоминает в чате этот сценарий, который лишает вышеупомянутый подход.
- 0000000000001
- 2
Поэтому, чтобы справиться с этим, вам нужно немного изменить тактику. Ядро вышеупомянутого подхода все еще можно использовать, однако нам нужно также ввести количество символов в результаты. Это дает возможность сортировать результаты по количеству символов в строках и их значениях.
$ for i in $(echo $str0 | grep -oP "\d+");do a=$(echo "$i" | wc -c); \ echo "$a $i"; done | sort -n | tail -1 | cut -d" " -f2
Результаты:
$ echo $str0 0000000000001a2test $ for i in $(echo $str0 | grep -oP "\d+");do a=$(echo "$i" | wc -c); \ echo "$a $i"; done | sort -n | tail -1 | cut -d" " -f2 0000000000001
Вы можете сконденсировать это немного, используя способность Bash определять длину переменной, используя ${#var}
.
$ for i in $(echo $str0 | grep -oP "\d+");do echo "${#i} $i"; done | \ sort -n | tail -1 | cut -d" " -f2 0000000000001
Использование `grep -P
Я решил использовать grep -P ...
выше, потому что я, будучи разработчиком Perl, как и синтаксис класса, говоря все такие цифры: \d+
, вместо [[:digit:]]\+
или [0-9]\+
. Но для этой конкретной проблемы это действительно не нужно. Вы могли бы так же легко поменять grep
который я использовал так:
$ .... grep -o "[0-9]\+" ....
Например:
$ for i in $(echo $str0 | grep -o "[0-9]\+");do echo "${#i} $i"; done | \ sort -n | tail -1 | cut -d" " -f2 0000000000001
Решение в perl
:
echo 212334123434test233abc44 | perl -nle 'print (( map { $_->[0] } sort{ $a->[1] <=> $b->[1] } map { [$_,length] } split /\D+/, $_)[-1] )' 212334123434
Рекомендации
- Преобразование Шварца
Используя python со строкой, переданной в командной строке, и предполагая, что вы хотите первую последовательность максимальной длины:
import sys longest = current = "" for x in sys.argv[1]: if current and not x.isdigit(): if len(current) > len(longest): longest = current current = "" else: current += x print(longest)
Вот еще один подход Perl, который может иметь дело с десятичными знаками, а также целыми числами:
echo "0.212334123434test233" | perl -lne 'while(/([\d.]+)/g){$max=$1 if length($1) > length($max)} print $max'
Обратите внимание, что ни один из ответов до сих пор не будет иметь дело с десятичными знаками, и поскольку вы указываете, что вы хотите получить самое длинное, а не численное наибольшее число, я предполагаю, что вам действительно нужны десятичные числа.
объяснение
-
perl -lne
:-n
означает «читать строки за строкой и запускать скрипт, заданный-e
на нем».-l
добавляет новую строку для каждого вызоваprint
(и другие вещи, которые здесь не актуальны). -
while(/([\d.]+)/g)
: итерация по всем числам (\d
означает[0-9]
, поэтому[\d.]
будет соответствовать цифрам и … Если вы также хотите найти отрицательные числа, add-
. Скобки заключают согласованную строку как$1
которая используется на следующем шаге. -
$max=$1 if length($1) > length($max)
: если длина текущего совпадения больше самого длинного ($max
), сохраните совпадение как$max
. -
print $max
: напечатать самую длинную строку найденных чисел. Это будет выполнено после завершения цикла while, поэтому после того, как все номера будут найдены.
Данный
str="212334123434test233"
затем в bash
max="" while read num; do (( ${#num} > ${#max} )) && max=$num done < <(grep -Eo '[0-9]+' <<< "$str") echo $max 212334123434
Возможно, более чистое решение bash, использующее массив, построенный путем замены нецифровых символов в строке пробелом вместо вместо grep
max="" declare -a nums="${str//[^[:digit:]]/ }" for num in ${nums[@]}; do (( ${#num} > ${#max} )) && max=$num done echo $max
Основываясь на ответе от @mikeserv, вот еще одна альтернатива. Он извлекает числа (по методу mikeserv), затем сортирует их по порядку и принимает последний. Запрещая ведущие нули, это даст вам наибольшее число (без учета знака):
echo 1111askdlfm2234 | printf %s\\n $(tr -sc 0-9 \ ) | sort -n | tail -1
bash и GNU sort
IFS=$'\0' read -rl _ < <(tr -cs '[:digit:]' '[\0*]' <<<'11abcde1234556ghijk22'| sort -znr) echo $l 1234556
Используйте нечисловые символы для разделения строки и найдите самую длинную последовательность или наибольшее числовое значение (для чисел с равной длиной) с тройным оператором.
$ echo "212334123434test233" | awk -F'[^0-9]+' '{for(i=1;i<=NF;i++){m=length($i)>=length(m)||$i>m?$i:m}};END{print m}' 212334123434
Вы можете также установить разделитель записей awk ( RS
) в любую нечисловую строку символов:
$ echo "212334123434test233" \ | awk -v RS='[^0-9]+' ' length(longest) < length($0) {longest = $0}; END{print longest}' 212334123434