Да, это [[:digit:]]
~[0-9]
~\d
(, где ~означает приблизительно ).
В большинстве языков программирования (, где это поддерживается)
\d ≡ `[[:digit:]]` # (is identical to, it is a short hand for).
\d
существует в меньшем количестве экземпляров, чем [[:digit:]]
(, доступный в grep -P
, но не в POSIX ).
В UNICODE много цифр , например:
123456789 # Hindu-Arabic
Арабские цифры٠١٢٣٤٥٦٧٨٩ # ARABIC-INDIC
۰۱۲۳۴۵۶۷۸۹ # EXTENDED ARABIC-INDIC/PERSIAN
߀߁߂߃߄߅߆߇߈߉ # NKO DIGIT
०१२३४५६७८९ # DEVANAGARI
Все из которых могут быть включены в [[:digit:]]
или \d
, и даже некоторые случаи [0-9]
.
Для конкретных POSIX BRE или ERE:\d
не поддерживается (не в POSIX, а в GNUgrep -P
). [[:digit:]]
требуется POSIX для соответствия классу цифровых символов,который, в свою очередь, требует от ISO C символов от 0 до 9 и ничего больше. Так что только в локали C все [0-9]
, [0123456789]
, \d
и [[:digit:]]
означают абсолютно одно и то же. [0123456789]
не имеет возможных неправильных интерпретаций, [[:digit:]]
доступен в большем количестве утилит и в некоторых случаях означает только [0123456789]
. \d
поддерживается несколькими утилитами.
Что касается [0-9]
, значение выражений диапазона определяется только POSIX в локали C; в других локалях это может быть другим (может быть порядок кодовой точки или порядок сортировки или что-то еще ).
Самый простой вариант для всех цифр ASCII.
Всегда действителен, (AFAICT )нет известных случаев сбоя.
Соответствует только английским цифрам:0123456789
.
Обычно считается, что [0-9]
— это только цифры ASCII 0123456789
.
В некоторых случаях это до боли неверно :Linux в какой-то локали, отличной от «C» (Июнь 2020 г. )Системы, например:
Предположим:
str='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'
Попробуйте grep
обнаружить, что он позволяет большинство из них:
$ echo "$str" | grep -o '[0-9]\+'
0123456789
٠١٢٣٤٥٦٧٨
۰۱۲۳۴۵۶۷۸
߀߁߂߃߄߅߆߇߈
०१२३४५६७८
У этого сэда проблемы. Следует удалить только 0123456789
, но удаляет почти все цифры. Это означает, что он принимает большинство цифр, но не некоторые девятки (???):
$ echo "$str" | sed 's/[0-9]\{1,\}//g'
٩ ۹ ߉ ९
То, что даже expr страдает теми же проблемами, что и sed:
expr "$str" : '\([0-9 ]*\)' # also matching spaces.
0123456789 ٠١٢٣٤٥٦٧٨
А также ред
printf '%s\n' 's/[0-9]/x/g' '1,p' Q | ed -v <(echo "$str")
105
xxxxxxxxxx xxxxxxxxx٩ xxxxxxxxx۹ xxxxxxxxx߉ xxxxxxxxx९
Существует множество языков :Perl, Java, Python, C. В которых[[:digit:]]
(и\d
)требуется расширенное значение. Например,этот perl-код будет соответствовать всем цифрам сверху:
$ str='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'
$ echo "$str" | perl -C -pe 's/[^\d]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
Что эквивалентно выбору всех символов, имеющих свойства Unicode Numeric
и digits
:
.
$ echo "$str" | perl -C -pe 's/[^\p{Nd}]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
Какой grep может воспроизвести (конкретная версия pcre может иметь другой внутренний список числовых кодовых точек, чем Perl):
$ echo "$str" | grep -oP '\p{Nd}+'
0123456789
٠١٢٣٤٥٦٧٨٩
۰۱۲۳۴۵۶۷۸۹
߀߁߂߃߄߅߆߇߈߉
०१२३४५६७८९
Некоторые реализации могут понимать диапазон как нечто отличное от простого порядка ASCII (ksh93, например)(при тестировании версии от мая 2018 г. (AT&T Research )93u+ 2012 -08 -01):
$ LC_ALL=en_US.utf8 ksh -c 'echo "${1//[0-9]}"' sh "$str"
۹ ߀߁߂߃߄߅߆߇߈߉ ९
Сейчас (июнь 2020 г. ), тот же пакет ksh93 из debian (та же версия sh (AT&T Research )93u+ 2012 -08 -01):
$ LC_ALL=en_US.utf8 ksh -c 'echo "${1//[0-9]}"' sh "$str"
٩ ۹ ߉ ९
И это кажется мне верным источником ошибок, ожидающих своего появления.
$ awk -F ':' '$1 == "Drive name" { saved = $0 } $0 == "failed to get drive stats" { print saved }' file
Drive name: id1,sd@n5000cca8749
Drive name: id1,sd@n5000cca4607
Это сначала устанавливает разделитель полей ввода равным :
. Затем он сохраняет строку в переменной saved
всякий раз, когда обнаруживается строка, указывающая имя диска.
Если в строке указано failed to get drive stats
, печатается текущее значение saved
.
Вот почему в awk есть "режим абзаца", все, что вам нужно, это:
$ awk -v RS= -F'\n' '/failed to get drive stats/{print $2}' file
Drive name: id1,sd@n5000cca8749
Drive name: id1,sd@n5000cca4607
Пробовал использовать метод "Ниже", и он работал нормально
awk '{a[++i]=$0}/failed/{for(x=NR-2;x<NR;x++)print a[x]}' filename| sed -n '1~2p'
выход
Drive name: id1,sd@n5000cca8749
Drive name: id1,sd@n5000cca4607