Sed заменить строку в первой строке абзаца - PullRequest
0 голосов
/ 26 января 2019

Я пытаюсь автоматизировать периодическое обнаружение и удаление файлов, используя fdupes. Я получил этот красивый сценарий:

# from here:
# https://www.techrepublic.com/blog/linux-and-open-source/how-to-remove-duplicate-files-without-wasting-time/

OUTF=rem-duplicates_2019-01.sh;

echo "#! /bin/sh" > $OUTF;

find "$@" -type f -printf "%s\n" | sort -n | uniq -d |
    xargs -I@@ -n1 find "$@" -type f -size @@c -exec md5sum {} \; |
    sort --key=1,32 | uniq -w 32 -d --all-repeated=separate |
    sed -r 's/^[0-9a-f]*( )*//;s/([^a-zA-Z0-9./_-])/\\\1/g;s/(.+)/#rm \1/;' >> $OUTF;
chmod a+x $OUTF; ls -l $OUTF

Создает файл со следующей структурой:

#! /bin/sh
#rm ./directory_a/file_a
#rm ./directory_b/file_identical_to_a

#rm ./directory_a/file_b
#rm ./directory_b/file_identical_to_b
#rm ./directory_c/another_file_identical_to_b

#rm ./directory_a/file_c
#rm ./directory_b/file_identical_to_c
#rm ./directory_c/another_file_identical_to_c
#rm ./directory_d/yet_another_file_identical_to_c

Я хочу удалить тег # из первой строки каждого абзаца, чтобы получить

rm ./directory_a/file_c
#rm ./directory_b/file_identical_to_c
#rm ./directory_c/another_file_identical_to_c
#rm ./directory_d/yet_another_file_identical_to_c

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

    sed -r 's/^[0-9a-f]*( )*//;s/([^a-zA-Z0-9./_-])/\\\1/g;s/(.+)/#rm \1/;s/\n\n#rm/\n\nrm/;' >> $OUTF;

Но не может SED распознать (\ n \ n) или любой другой указатель, который я могу вспомнить в начале абзаца. Что я делаю не так?

Редактировать: я не могу редактировать комментарий, поэтому вот последний сценарий:

TEMPF=temp.txt;
OUTF=rem-duplic_2019-01.sh

echo "#! /bin/sh" > $TEMPF;

find "$@" -type f -printf "%s\n" | sort -n | uniq -d |
    xargs -I@@ -n1 find "$@" -type f -size @@c -exec md5sum {} \; |
    sort --key=1,32 | uniq -w 32 -d --all-repeated=separate |
    sed -r 's/^[0-9a-f]*( )*//;s/([^a-zA-Z0-9./_-])/\\\1/g;s/(.+)/#rm \1/' >> $TEMPF;
awk -v a=2 '/^$/{a=2}!--a{sub(/#/,"")}1' $TEMPF > $OUTF

chmod a+x $OUTF; ls -l $OUTF
rm $TEMPF

Ответы [ 5 ]

0 голосов
/ 28 января 2019

Просто используйте Perl с режимом абзаца

perl -00 -pe ' s/^#// ' 

Со входами

$ cat yozzarian.txt
#! /bin/sh
#rm ./directory_a/file_a
#rm ./directory_b/file_identical_to_a

#rm ./directory_a/file_b
#rm ./directory_b/file_identical_to_b
#rm ./directory_c/another_file_identical_to_b

#rm ./directory_a/file_c
#rm ./directory_b/file_identical_to_c
#rm ./directory_c/another_file_identical_to_c
#rm ./directory_d/yet_another_file_identical_to_c
$ perl -00 -pe ' s/^#// ' yozzarian.txt
! /bin/sh
#rm ./directory_a/file_a
#rm ./directory_b/file_identical_to_a

rm ./directory_a/file_b
#rm ./directory_b/file_identical_to_b
#rm ./directory_c/another_file_identical_to_b

rm ./directory_a/file_c
#rm ./directory_b/file_identical_to_c
#rm ./directory_c/another_file_identical_to_c
#rm ./directory_d/yet_another_file_identical_to_c
$
0 голосов
/ 27 января 2019

Это может сработать для вас (GNU sed):

sed '/^#!\|^\s*$/{n;s/.//}' file

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

0 голосов
/ 27 января 2019

С седом:

sed "1n;/^#/,/^$/{ s///;}" file
0 голосов
/ 27 января 2019

Вместо этого используйте awk:

awk '/^$/{a=1} !a--{sub(/#/,"")} 1' a=1 file
  • /^$/ { a = 1 } означает установить a в 1, если текущая строка пустая,
  • !a-- является сокращением для a-- == 0, следующее действие ({ sub(/#/, "") }) удаляет первый # из текущей строки,
  • 1 означает печать всех строк,
  • a=1 требуется для удаления # из строки после Шебанга (т.е. 2-й строки).
0 голосов
/ 27 января 2019

Вы также можете использовать это:

sed '/^$\|^#!/{N;s/#r/r/}' input.txt

не стесняйтесь добавлять опцию на месте, если хотите

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...