Не анализировать ls
если можно помочь ему. В зависимости от того, что Вы делаете, test
утилита могла бы быть лучшей альтернативой.
test -r filename
возвратит успех, если файл будет читаем с полномочиями текущего пользователя и перейдет по символьным ссылкам автоматически. Аналогично, -w
и -x
скажет Вам, если файл будет перезаписываем или исполняем. test
команда указана POSIX и так должна работать с любым современным UNIX.
Если действительно необходимо знать определенные полномочия файла, ls
мог бы быть самый портативный путь, пока Вы только используете его на одном файле за один раз. В этом случае, -L
и -l
флаги также указаны POSIX, таким образом, необходимо быть довольно в безопасности. (См., "не Анализируют ls
"для немного большего количества комментария относительно мобильности выходных полей ls -l
.)
Другая опция могла бы состоять в том, чтобы записать короткую программу C для использования в своих интересах stat(2)
системный вызов, который будет доступен на каждом UNIX под солнцем. Если это - небольшая часть большей части программного обеспечения, это уже компилируется от C, это могло бы быть наилучшим вариантом.
Ответ
perl -0777 -p -i -e 's/,(\n*)\Z/\1/m' *.txt
удалит последнее'', во всех файлах, заканчивающихся в .txt
, если'', сопровождается только 0-more символами новой строки затем конец файла.
От Вашего примера:
reedm@www:~/tmp $ cat > test.txt
blah blah blah,
blah blah blah,
blah blah blah,
reedm@www:~/tmp $ perl -0777 -p -i -e 's/,(\n*)\Z/\1/m' *.txt
reedm@www:~/tmp $ cat test.txt
blah blah blah,
blah blah blah,
blah blah blah
reedm@www:~/tmp $
Wat?
Perl является тайным зверем в лучшие времена, и остроты жемчуга могут быть особенно загадочными.
-e
флаг позволяет нам передавать программу жемчуга командной строке. В этом случае 's/regex/replace/flags'' является программой.
-p
отметьте жемчуг причин для применения предоставленной программы в цикле по каждой "строке" (см. -0
) для каждого обеспеченного имени файла.
-i
отметьте жемчуг причин, чтобы заменить файл выводом программы, вместо того, чтобы печатать вывод к стандарту.
-0
отметьте изменения что использование жемчуга разделителя повредить файл в "строки". 0777
специальное значение, используемое условно, чтобы заставить жемчуг считать весь файл в единственную "строку".
Регулярное выражение является несколько сложным при помощи нескольких perl-определенных приемов:
m
флаг в конце заставляет regex воздействовать на несколько строк.,
просто, и соответствует единственной, литеральной запятой.(\n*)
соответствия 0-more новые строки подряд, и хранят их как подшаблон ( (
и )
символы обозначают подшаблон). Поскольку это - первый подшаблон, мы можем использовать \1
в заменяющем разделе для значения "независимо от того, что этот подшаблон соответствовал".\Z
жемчуг определенное расширение и соответствует концу строки, работало с - в этом случае, это - весь файл.\1
заменять соответствие только серией новых строк, удаляя запятую.Для получения информации о человеке о регулярных выражениях жемчуга и флагах командной строки жемчуга, проверьте страницы справочника для perlre
и perlrun
соответственно.
Если решение для Perl хорошо для Вас:
perl -00pe 's/(.*),/$1/s' file
Сохранить изменения в самом файле:
perl -i -00pe 's/(.*),/$1/s' file
Применять это на несколько файлов:
perl -i -00pe 's/(.*),/$1/s' *.txt
perl -00pe 's/(.*),/$1/s' *.txt
? Я пробовал его, но все, что это, кажется, делает, выведено содержание файлов на терминальный экран, не внося изменений.Прошу прощения... Я ничего не знаю о perl
.
– Questioner
21.02.2013, 08:25
На больших файлах используйте ответ Гуру, это быстрее. На маленьких файлах (<25 строк), однако, я нашел, что это было немного быстрее (предположение, что у Вас есть GNU tac):
tac file | awk '!/^[[:blank:]]*$/{i++;if(i==1){sub(",$","")}}1' | tac
sed
может быть помещен в многострочный поиск и режим замены так, чтобы он мог обработать все содержание файла как одну строку в "пространстве шаблона".
(Примечание: FreeBSD sed
требует последовательности опции -n -i -e
для корректного оперативного редактирования файла.)
# delete the last , in the last non-empty line of a file
# cf. http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/
cat -n testfile
sed -n -i -e '
# if the first line copy the pattern to the hold buffer
1h
# if not the first line then append the pattern to the hold buffer
1!H
# if the last line then ...
$ {
# copy from the hold to the pattern buffer
g
# remove last , in last non-empty line of file
#s/,\([^,[:cntrl:]]*\n*\)$/\1/
s/,\([^,]*\)$/\1/
p
}' testfile
perl -0777 -p -i -e 's/,(\n*)\Z/\x\1/m'
– Digger 17.03.2016, 06:21