정규식이 포함된 경우 sed에서 파일을 건너뛰는 방법은 무엇입니까?

정규식이 포함된 경우 sed에서 파일을 건너뛰는 방법은 무엇입니까?

현재 다음을 사용하고 있습니다단순화된 명령에게후행 공백 제거그리고파일 끝에 개행 추가필요한 경우:

find . -type f -exec sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' {} \+

곧 알게 되겠지만 여기에는 두 가지 문제가 있습니다.바이너리 파일파일 끝에 개행 문자를 추가합니다.␍␊ 줄 구분 기호. 이러한 수정 사항은 커밋 등을 할 때 실행 취소하거나 건너뛰기가 쉽지만 git gui되돌리는 양을 최소화*하고 싶습니다. 마지막까지:

건너뛰는 방법이 있나요?전체다음과 같은 경우 파일을 제출하세요.어느sed라인은 ? 의 정규식과 일치합니다 .

* ␀ 문자가 없는 바이너리 파일이 있을 수도 있고, 의도적으로 개행이나 ␀를 혼합한 파일이 있을 수도 있다는 것을 알고 있습니다. 하지만 저는 최소한의 인간 개입이 필요한 솔루션을 찾고 있습니다. 나~할 수 있었다아마도 작업하려는 모든 파일 확장자를 나열할 수 있지만 지속적으로 검토해야 하는 매우 긴 목록이 될 것이며 이름 충돌로 인해 바이너리 파일이 빠져나갈 가능성이 여전히 있을 것입니다.

복잡한해결 방법:

while IFS= read -r -d '' -u 9
do
    if [[ "$(file -bs --mime-type -- "$REPLY")" = text/* ]]
    then
        sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' -- "$REPLY"
    else
        echo "Skipping $REPLY" >&2
    fi
done 9< <(find . -type f -print0)

답변1

git바이너리 파일이 무엇인지 아닌지에 대한 의 관점을 신뢰한다면 git grep바이너리가 아닌 파일 목록을 얻는 데 사용할 수 있습니다. t.cpp텍스트 파일이고 ls바이너리이며 둘 다 체크인되었다고 가정합니다 .

$ ls
t.cpp ls
$ git grep -I --name-only -e ''
t.cpp

옵션 -I의 의미는 다음과 같습니다.

-I
바이너리 파일의 패턴과 일치하지 마세요.

이를 표현식과 결합하려면 다음을 수행하십시오 sed.

$ git grep -I --name-only -z -e '' | \
       xargs -0 sed -i.bk -e 's/[ \t]\+\(\r\?\)$/\1/;$a\'

( -z/ xargs -0이상한 파일 이름을 처리하는 데 도움이 됩니다.)

git grep다른 유용한 옵션에 대해서는 매뉴얼 페이지를 확인하십시오 . --no-index또는 --cached작업하려는 파일 세트가 정확히 무엇인지에 따라 도움이 될 수 있습니다.

답변2

sed의 정규식과 일치하는 줄이 있으면 전체 파일을 건너뛸 수 있는 방법이 있습니까?

예, 그렇습니다.

# test case for skipping file if a sed regex match succeeds

echo 'Hello, world!' > hello_world.txt
cat hello_world.txt
ls -li hello_world.txt

sed -i -e '/.*Hello.*/{q;}; s/world/WORLD/g' hello_world.txt # skips file
sed -i -e '/.*HeLLo.*/{q;}; s/world/WORLD/g' hello_world.txt

답변3

다음은 해당 인수(파일 이름이어야 함)를 반복하고 개행으로 끝나지 않는 모든 파일에 개행을 추가하는 Perl 스크립트입니다. 널 바이트가 포함된 파일은 건너뜁니다. 이미 개행 문자로 끝나는 파일은 수정되지 않습니다. CR이 포함된 파일에는 CRLF가 추가되고 다른 파일에는 LF만 추가됩니다. 테스트되지 않았습니다.

#!/usr/bin/env perl
foreach my $f (@ARGV) {
    open F, "<", $f or die;
    my $last = undef;
    my $cr = 0;
    while (<>) {if (/\0/) {undef $last; break} $last = $_; ++$cr if /\r$/}
    close F;
    if (defined $last && $last !~ /\n\Z/) {
        open F, ">>", $f or die;
        print($cr ? "\r\n" : "\n");
        close F or die;
    }
}

관련 정보