Как я могу заменить текст в последней непустой строке?

Не анализировать ls если можно помочь ему. В зависимости от того, что Вы делаете, test утилита могла бы быть лучшей альтернативой.

test -r filename возвратит успех, если файл будет читаем с полномочиями текущего пользователя и перейдет по символьным ссылкам автоматически. Аналогично, -w и -x скажет Вам, если файл будет перезаписываем или исполняем. test команда указана POSIX и так должна работать с любым современным UNIX.

Если действительно необходимо знать определенные полномочия файла, ls мог бы быть самый портативный путь, пока Вы только используете его на одном файле за один раз. В этом случае, -L и -l флаги также указаны POSIX, таким образом, необходимо быть довольно в безопасности. (См., "не Анализируют ls"для немного большего количества комментария относительно мобильности выходных полей ls -l.)

Другая опция могла бы состоять в том, чтобы записать короткую программу C для использования в своих интересах stat(2) системный вызов, который будет доступен на каждом UNIX под солнцем. Если это - небольшая часть большей части программного обеспечения, это уже компилируется от C, это могло бы быть наилучшим вариантом.

4
13.04.2017, 15:36
4 ответа

Ответ

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 соответственно.

2
27.01.2020, 20:48
  • 1
    Для любого, кто должен изменить вышеупомянутую остроту жемчуга для обработки случая, где Вы хотите добавить текст в конец последней непустой строки (в этом случае, добавляя "x" к запаздывающей запятой в последней строке), попытка perl -0777 -p -i -e 's/,(\n*)\Z/\x\1/m' –  Digger 17.03.2016, 06:21

Если решение для Perl хорошо для Вас:

 perl -00pe 's/(.*),/$1/s' file

Сохранить изменения в самом файле:

perl -i -00pe 's/(.*),/$1/s' file

Применять это на несколько файлов:

perl -i -00pe 's/(.*),/$1/s' *.txt
3
27.01.2020, 20:48
  • 1
    Это работает над несколькими файлами? Как perl -00pe 's/(.*),/$1/s' *.txt? Я пробовал его, но все, что это, кажется, делает, выведено содержание файлов на терминальный экран, не внося изменений.Прошу прощения... Я ничего не знаю о perl. –  Questioner 21.02.2013, 08:25
  • 2
    @DaveMG: обновленный решение для Вашего требования... –  Guru 21.02.2013, 08:39
  • 3
    Так закройтесь..., команда удалила запятую из конца каждой строки. Извините, если это не ясно в вопросе. Я просто хочу удалить запятую только из последней непустой строки. –  Questioner 21.02.2013, 08:44

На больших файлах используйте ответ Гуру, это быстрее. На маленьких файлах (<25 строк), однако, я нашел, что это было немного быстрее (предположение, что у Вас есть GNU tac):

tac file | awk '!/^[[:blank:]]*$/{i++;if(i==1){sub(",$","")}}1' | tac
3
27.01.2020, 20:48

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
2
27.01.2020, 20:48

Теги

Похожие вопросы