Тестирование "tail -c 1" в bash - PullRequest
1 голос

В Linux - проверьте, есть ли пустая строка в конце файла , в некоторых сообщениях для сравнения символов используются [[ ]] и ==.

Я быЯ хотел написать однострочную команду для обнаружения, если в EOF нет новой строки, и я столкнулся с этой маленькой проблемой.

В выводе echo есть \n в конце.

$ echo echo | od -c           
0000000   e   c   h   o  \n
0000005
$ echo -n echo | od -c           
0000000   e   c   h   o
0000004

Если я соединю [[ ]] и == вместе, то я не получу ожидаемый результат.

$ [[ `echo echo | tail -c1` == "\n" ]] && echo true
$ [[ `echo echo | tail -c1` != "\n" ]] && echo true
true
$ [[ `echo -n echo | tail -c1` != "\n" ]] && echo true
true

Как показано od -c, вывод echo echo | tail -c1равно \n, а [[ "\n" == "\n" ]] && true вернет true, поэтому я ожидаю, что первая команда выдаст true.Тем не менее, почему он оценивается как пустая строка?

Спасибо за чтение!

Ответы [ 2 ]

2 голосов
/ 10 мая 2019

Как четко указано в Справочное руководство Bash :

Bash выполняет расширение, выполняя команду в среде подоболочек и заменяя подстановку команд стандартным выводомкоманда, с удаленными любыми завершающими символами новой строки.

Включите флаг -x, чтобы увидеть, что происходит ясно:

$ set -x
$ [[ `echo echo | tail -c 1` == '\n' ]]
++ tail -c 1
++ echo echo
+ [[ '' == \\\n ]]
$
$ echo "$(echo)"
++ echo
+ echo ''

И как sidenote, даже если завершающие символы новой строки не были обрезаны, ваше сравнение не вернет true, потому что '\n' - это не перевод строки, а буквально обратный слеш, за которым следует буква n.Вы должны использовать $'\n', чтобы получить фактический перевод строки.

1 голос
/ 10 мая 2019

Что касается решения, вы можете использовать следующее:

$ printf 'test\n' | perl -0777ne'exit(/\n\z/?0:1)' || echo "Missing line feed" >&2

$ printf 'test'   | perl -0777ne'exit(/\n\z/?0:1)' || echo "Missing line feed" >&2
Missing line feed

или

$ printf 'test\n' | perl -0777ne'die("Missing line feed\n") if !/\n\z/'

$ printf 'test'   | perl -0777ne'die("Missing line feed\n") if !/\n\z/'
Missing line feed
...