Как мне получить только цифры в grep?
Я хочу найти вхождение чисел в вышеуказанный файл. Я придумал:
Скорее хочу только 34 . Есть ли способ сделать это?
В будущем также ознакомьтесь со справочной страницей для grep (или любой другой программы). Страница man подробно описывает параметры, необходимые для многих распространенных применений программы. напр. man grep
Вы можете использовать grep -E для доступа к расширенному синтаксису регулярного выражения (То же, что egrep )
Я создал тестовый файл с содержанием ниже:
>cat testfile this is some text with some random lines again some text ok now going for numbers (:32) ok now going for numbers (:12) ok now going for numbers (:132) ok now going for numbers (:1324)
Теперь, чтобы извлечь только цифры из текста, который вы можете использовать
>grep -Eo '1' testfile 32 12 132 1324
Здесь «-o» используется только для вывода соответствующего сегмента строки, а не полного содержимого строки.
Квадратные скобки (например, ) указывают количество совпадений. требует, чтобы предыдущий символ или класс символов встречался хотя бы один раз, но не более четырех раз.
Приятно. Кроме того, чтобы соответствовать более 4 или произвольному количеству цифр, используйте grep -Eo ‘9<1,>‘ testfile1,>
Вы можете использовать скобочное выражение RE, [:digit:] указанное в разделе 9.3.5 стандарта POSIX , в сочетании с -o флагом для печати только соответствующих «слов»
$ grep -o '[[:digit:]]*' $'No number in this line\nbut 123 here' 123
grep -o будет печатать только соответствующую часть строки. В противном случае grep напечатает любые строки с шаблоном.
Я бы использовал curl для локального или удаленного доступа к вашему файлу, затем я бы собрал строки с числами, завернутыми в (:), затем обрезал эти фрагменты и записал в файл
принятый ответ игнорирует, что в предыдущих строках файла могут быть числа, он работает для данных примера, но что, если файл был удаленным?
curl file:///home/$USER/Public/input.txt | grep -o '(:.*)' | cut -d ":" -f 2 | cut -d ")" -f 1 > output.txt
В этом примере output.txt в вашей текущей папке будет перезаписано, мы получаем доступ input.txt из вашей общей папки.
curl https://yoursite.com/Public/input.txt | grep -o '(:.*)' | cut -d ":" -f 2 | cut -d ")" -f 1 > output.txt
sed, capture only the number
I cannot think on a one-liner, so this is my approach:
while read line do grep -Po '(?<=A=)\d+' <<< "$line" || echo "0" done < file
I am using the look-behind grep to get any number after A= . In case there is none, the || (else) will print a 0 .
This prepends A=0 to the line before substituting.
Ah, I like your solution better. Is the \< thing making sure you get the last 'A='? What does it actually do?
@cluracan, We always get the last A= because .* is greedy. That's why we prepend A=0 instead of appending.
kent$ echo "some text A=10 some text some more text A more text some other text A=30 other text"|awk -F'A=' 'NF==1' 10 0 30
This might work for you (GNU sed):
Look for the string A= followed by one or more numbers and if it occurs replace the whole line by the back reference. Otherwise replace the whole of the line by 0 .
+1 this is the only one that is 100% sed, is accurate enough and actually works (and also quite short). b.t.w. what does the ;t; between the two replacements ? (oh, btw, you even can scrap one of the 9 from the pattern) 🙂
@thom t checks to see if the last substitute command (if any) was a success and if so bails out. As there is no goto place name following the t command it ends the processing of the line. If the substitution was not a success (or no substitute has been done) it replaces the whole line with a 0 .
Выделение числа из строки в выводе команды (Bash)
В переменной WAYSCAN хранится путь к утилите wayland-scanner. Необходимо получить версию этой утилиты и поместить её в другую переменную, однако вывод wayland-scanner --version выводит строку wayland-scanner 1.16.0 . Мне нужно из этой строки выделить только число. Знаю что это можно сделать с помощью регулярки, но как не пытался - не получается. Может кто подсказать решение, пожалуйста? Только чтобы работало как в Linux, так и BSD
Как в bsd не знаю, в linux можно так
wayland-scanner --version 2>&1 | egrep -o "3.*$"
wayland-scanner --version 2>&1 | awk ''
[20:16] u@notebook:~> echo 'wayland-scanner 1.16.0' | cut -d' ' -f2 1.16.0
Зачем тебе регулярки, если можно просто через col2 пропустить?
ver=$(wayland-scanner --version) echo $ver wayland-scanner 1.16.0 ver=$ echo $ver 1.16.0
legolegs ★★★★★ ( 25.01.19 21:20:33 MSK )
Последнее исправление: legolegs 25.01.19 21:21:34 MSK (всего исправлений: 1)
legolegs best.
Сделал так, однако получаю на выходе Illegal Number, а условие со сравнением версий отрабатывается некорректно (переменной CODEGEN всегда присвается значение «private-code»). Где ошибка?
#!/bin/sh WAYSCAN=/usr/bin/wayland-scanner WAYSCAN_VER=$($WAYSCAN --version 2>&1 | awk '') WAYLAND_PROTOS=/usr/share/wayland-protocols OUTPUT=gfx/common/wayland if [ ! -d $WAYLAND_PROTOS ]; then WAYSCAN=/usr/local/bin/wayland-scanner WAYLAND_PROTOS=/usr/local/share/wayland-protocols fi if [ ! -d $OUTPUT ]; then mkdir $OUTPUT fi #Since Wayland 1.15 option "code" is deprecated. Recommended to use "private-code" option instead. if [ "$WAYSCAN_VER -ge 1.15" ]; then CODEGEN=private-code else CODEGEN=code fi
Понял. Дело в том, что пытаюсь сравнить дробные числа. Не подскажите как правильно всё сделать?
Про illegal number не понял, а по поводу сравнения версий, да, это так не работает.
CHECK="1.17" if [ "$(printf '%s\n' "$WAYSCAN_VER" "$CHECK" | sort -V | tail -1)" == "$WAYSCAN_VER" ]; then CODEGEN=private-code else CODEGEN=code fi + CHECK=1.17 ++ printf '%s\n' 1.16.0 1.17 ++ sort -V ++ tail -1 + '[' 1.17 == 1.16.0 ']' + CODEGEN=code
CHECK="1.15" if [ "$(printf '%s\n' "$WAYSCAN_VER" "$CHECK" | sort -V | tail -1)" == "$WAYSCAN_VER" ]; then CODEGEN=private-code else CODEGEN=code fi + CHECK=1.15 ++ printf '%s\n' 1.16.0 1.15 ++ sort -V ++ tail -1 + '[' 1.16.0 == 1.16.0 ']' + CODEGEN=private-code
Мне нужно чтобы было >=1.15. Пытаюсь реализовать с помощью bc, но пока не получается
Так выше я привел код, который позволит сравнить версии.
А, хорошо, спасибо. Я просто не совсем понял как он работает. Но работает 🙂
-V, --version-sort natural sort of (version) numbers within text
Выводим сравниваемые версии в формате одна версия на одну строку. Потом с помощью sort -V распределяем их в образовавшейся колонке от меньшей версии к большей. tail'ом берем значение большей. Дальше сравниваем с полученной реальной версией wayland-scan. Если она равна самой большой версии, значит версия wayland-scan или той же версии, что и значение CHECK, т.е. 1.15, или выше. А если самая большая версия после tail не совпадает с версией wayland-scan, значит версия wayland-scan меньше.
Взгруснулось. Аж на комментарии хватило энтузиазма.
#!/usr/bin/env bash # compare version from $1 and $2 # parse the format "(programm_name[- ])?[[:num:]+](\.[[:num:]]+)*(-suffix)?" # ignore comparing a programm name and a suffix # returns: 0 - $1=$2, 1 - $1>$2, 2 - $1 vercmp() < local -a va1 va2 local ps='^(..*[- ])?(54*(.33*)*)(-..*)?$' IFS=. # test the format and remove if present programm_name[- ] and -suffix [[ $1 =~ $ps ]] || return 3 # set array=(ver_major ver_minor ver_patch. ) va1=($) # for $2 too [[ $2 =~ $ps ]] || return 4 va2=($) local -i i=0 c1 c2 while [[ "$$" ]]; do # Removing leading zeroes, set empty as 0 c1=$((10#$)) c2=$((10#$)) # compare a version item [[ c1 -lt c2 ]] && return 2 [[ c1 -ne c2 ]] && return 1 i=i+1 done return 0 > # testing tests() < vercmp "$1" "$2" echo "'$1' '$2' $? returned" > tests 1 0 tests 0 1 tests 1 1 tests 1.1 0 tests 0 1.1 tests 1 1.1 tests 1.1 1.1 tests 1.1 1 tests 1.2 tests a-1.3 b-1.3-suff tests a-1.3 a-1.25 tests "b0 " tests "c0 1" "c0 0.1" tests 1.2.8-suff 1.2.010-suff tests "p 1" "x 1.0" tests "p 1." "x 1.0" tests "p.1." "x.1.0" tests "p.1" "x.1.0"
vodz ★★★★★ ( 26.01.19 12:43:42 MSK )
Последнее исправление: vodz 26.01.19 12:52:40 MSK (всего исправлений: 2)
How do I fetch only numbers in grep?
Here "-o" is used to only output the matching segment of the line, rather than the full contents of the line.
The squiggly brackets (e.g. < and >) indicate the number of instances of the match. requires that the previous character or character class must occur at least once, but no more than four times.
@FractalSpace when have the constrain of repeating at least one time in 7 <1,>, the -o option might not necessary, since repeating at least one time, by definition remove the empty output?1,>
You can use RE bracket expression [:digit:] specified by section 9.3.5 of POSIX standard , in combination with -o flag to print only matching "words"
You can use Perl style regular expressions as well
-P Interpret PATTERNS as Perl-compatible regular expressions (PCREs).
-o Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.
grep -o will print only the matching part of the line. Otherwise grep will print any lines with the pattern.
I would use curl to access your file locally or remotely, then I would grep lines with numbers wrapped in (: ) then cut those pieces off and write to file
the accepted answer ignores there could be numbers in the previous lines of the file, it does work for the example data, but what if the file was remote?
curl file:///home/$USER/Public/input.txt | grep -o '(:.*)' | cut -d ":" -f 2 | cut -d ")" -f 1 > output.txt
In this example output.txt in your current folder will be written over, we are accessing input.txt from your Public folder.
curl https://yoursite.com/Public/input.txt | grep -o '(:.*)' | cut -d ":" -f 2 | cut -d ")" -f 1 > output.txt