sed替换段落第一行中的字符串

时间:2019-01-26 19:12:25

标签: regex awk sed

我正在尝试使用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 :(得分:1)

使用sed:

sed "1n;/^#/,/^$/{ s///;}" file

答案 1 :(得分:0)

您也可以使用它:

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

如果需要,可以随意添加就地选择

答案 2 :(得分:0)

改为使用awk:

awk '/^$/{a=1} !a--{sub(/#/,"")} 1' a=1 file
  • /^$/ { a = 1 }表示如果当前行为空白行,则将a设置为1,
  • !a--a-- == 0的简写,操作({ sub(/#/, "") })之后从当前行中删除第一个#
  • 1表示打印所有行,
  • a=1必须从shebang之后的行(即第二行)中删除#

答案 3 :(得分:0)

这可能对您有用(GNU sed):

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

如果当前行是shebang或空行,则将其打印并删除下一行的第一个字符。

答案 4 :(得分:0)

只需在段落模式下使用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
$