2013-06-05 3 views
8

Что такое лучший способ проверить, если полное содержание файла соответствует регулярному выражению, такие какRegex совпадают все содержимое файла в Баш

^[0-9]{9}$ 

т.е., всего 9 номеров и больше ничего, ни разрывы строк , а не несколько наборов чисел.

Вот один вариант у меня есть, что мне не очень нравится:

cat -vt curloutput.txt | tr "\n" " " | egrep "^[0-9]{9}$" 

Редактировать

Я использую принятое решение так:

grep --perl-regex "(?m)(?<!.)^\d{9}$(?!.)" 

с помощью GNU Grep.

+0

ли вы имеете в виду каждую строку файла, имеющего этот формат или являясь всем файлом именно этого? – fedorqui

+0

Весь файл должен быть именно этим. – tomsv

+0

Вы хотите напечатать номер, имя файла, если оно совпадает, y/n или печать без значения выхода? – Kevin

ответ

5

Это регулярное выражение спичек «состоящих из 9 цифр» и (?m) делает каретку и доллар матч после/до символа новой строки, так что работает, чтобы предотвратить несколько строк:

(?m)(?<!.)^\d{9}$(?!.) 

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

Смотрите эту demonstrated on rubular, увидеть, как добавление любых других символов на 9-значного ввода текста на, хотя бы один символ новой строки, приведет в не матч

+0

Не будет работать, будет соответствовать первой новой строке. Файл, содержащий '123456789 \ nabce', по-прежнему будет соответствовать (соответствует первой новой строке), которую OP не хочет. – brice

+0

это неверно: он просто проверяет, есть ли у вас только цифры, а не только 9 из них и только 1 строка ... –

+0

@oli вопрос был отредактирован после того, как я опубликовал. Я думаю, что я поставил свой ответ на новый вопрос. У меня нет командной строки, чтобы проверить ее. – Bohemian

6

Test, что LineCount 1 затем проверить, что строка совпадает с регулярное выражение:

test $(wc -l file.txt | cut -f 1 -d ' ') = 1 \ 
    && grep -Eq '^[0-9]{9}$' file.txt && echo "match" 

Ломая команду, это то, что происходит:

#get the linecount 
wc -l file.txt | cut -f 1 -d ' ' 

# Check if there is a match in the file 
# result will be return value of the program so it can be used 
# directly with the AND operator 
grep -Eq '^[0-9]{9}$' file.txt 

Вы можете быть еще более ограничительный характер путем подсчета ВУ tes с wc:

test $(wc -c file.txt | cut -f 1 -d ' ') -eq 9 

Которая поймает конечную новую линию, если это необходимо. (-m будет считать символы вместо этого, в случае, если вы используете многобайтовые символы)

+0

после отправки быстро взбитого (и неправильного) ответа, я удалил его, и я запустил ваш: проверяя, что есть 1 строка, и что строки соответствуют вводу, заботятся обо всех оговорках: повторений регулярного выражения нет и что это на самом деле present (мое «решение» удалило регулярное выражение только в 1-й строке, используя 'sed -e '1s/regexp //'' и проверив результат в 0 байт, но входной файл с 0 байтами также соответствовал бы этим условиям ...) –

+1

Вместо 'test -n" $ MATCH "', вы должны просто использовать возвращаемое значение grep напрямую: '... && grep -q ...'. – Kevin

+1

'wc -l' подсчитывает только символы новой строки. Представьте себе файл без новой строки/только одной строки, а затем EOF. 'echo -n" 123456789 "> test; тест кошки | wc -l' будет печатать '0' – bartimar

1

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

[[ $(stat -c %s $f) -eq 9 && $(<$f) =~ ^[0-9]{9}$ ]] && echo y || echo n  

испытания:

$ f=/etc/passwd 
$ [[ $(stat -c %s $f) -eq 9 && $(<$f) =~ ^[0-9]{9}$ ]] && echo y || echo n 
n 

$ f=$(mktemp) 
$ printf "123456789" >| $f 
$ [[ $(stat -c %s $f) -eq 9 && $(<$f) =~ ^[0-9]{9}$ ]] && echo y || echo n 
y 
+0

Я не знал о '= ~' спасибо +1 – brice

+0

Это может быть удобно, хотя шаблоны расширения bash для файлов также довольно мощные. Одна вещь о rexxs bash: не цитируйте их, иначе они рассматриваются как простые строки. Может стать довольно беспорядочным, когда вы комбинируете переменные и метамарки регулярных выражений. –

1
awk 'END{if(NR == 1 && /^[0-9]{9}$/)print}' test.in 

Это печатает число тогда и только тогда, когда существует одна линия, и она соответствует шаблону.

Если вы просто хотите, возвращаемое значение как grep -q, вы можете использовать это:

awk 'END{exit !(NR == 1 && /^[0-9]{9}$/)}' test.in 
+0

Awk кажется правильным инструментом, но я только что попробовал свои две команды, и ни один из них не работает. – brice

+0

Какая версия awk у вас есть? – Kevin

+0

Оба работают на меня как на gnu, так и на BSD (mac) awks. – Kevin

1

Вы можете использовать чистый тест Oneliner

[[ `cat $file` =~ ^[0-9]{9}$ ]] && exit 0 || exit 1 
Смежные вопросы