파일에서 정확한 줄이 있으면 제거하고 나머지 줄은 유지합니다. 오류 처리 - 처리 방법

파일에서 정확한 줄이 있으면 제거하고 나머지 줄은 유지합니다. 오류 처리 - 처리 방법

텍스트 처리를 어떻게 해야 좋은 방법인지 잘 모르겠어서 여쭤보겠습니다.

다음 파일이 있습니다. ~/.config/mpv/input.conf다른 옵션도 포함될 수 있습니다 v disable.

파일에서 해당 줄을 제거하려면 다음과 같이 하면 됩니다.

grep -v -q -F 'v disable' input.conf; echo $?
1

여기서 - 파일에 현재와 같은 다른 내용이 포함되어 있지 않으면 1(매뉴얼 페이지"선택된 행이 없습니다." 라고 말합니다 1. 간단한 if-statement.

그래서 $?명령 다음에 저장한 다음 오류가 있으면 1보다 큰지 확인해야 합니다.

또한 파일을 제자리에 바꾸는 것이 좋은 생각인지 확실하지 않습니다.

grep ... input.conf > input.conf

다른 방법이 있으면 알려주세요. 또한 내 제안 중 일부가 올바른지 알려 주시기 바랍니다.

감사하고 응원합니다.


편집 1:

원하는 동작은 행이 존재하는 상태 사이를 전환하는 것입니다( >>행이 존재하는지 확인한 후 간단한 추가로 수행(제거, 따라서 질문)).

편집 2:

허용되는 솔루션은 POSIX와 호환되어야 합니다. 아니요바시즘또는 비 POSIX 도구. 그러나 다른 사람에게 유용할 수 있는 비 POSIX 솔루션을 포함할 수 있습니다. 어쨌든 감사합니다.

답변1

일반적으로 grep하나 이상의 행이 사용자가 제공한 RE와 일치하면 0(true)이 반환됩니다. 이 -v플래그는 이를 반전시키므로 grepRE와 일치하지 않는 모든 행은 성공한 것으로 간주됩니다. 이 경우 일치가 실패하는 유일한 경우 v는 소스 코드에 한 줄만 있고 RE와 정확히 일치하는 경우입니다.

따라서 일치하는 행을 삭제하고 적용된 변경 사항 표시를 반환하는 것은 약간 더 복잡합니다.

remove='v disable'
if grep -qxF "$remove" input.conf
then
    # Apply the removal, saving a backup
    cp -fp input.conf input.conf.bak &&
        grep -vxF "$remove" input.conf.bak >input.conf

    # Do other things that are relevant if the line was removed
else
    # Do things that are relevant if the line was not present
    :
fi

의 대체 제안발렌틴 바지라미끝났다댓글에서사용ed해당 위치에서 파일을 직접 수정합니다.

if printf '%s\n' '/^v disable/d' wq | ed -s input.conf >/dev/null
then
    # Do other things that are relevant if the line was removed
    :
else
    # Do things that are relevant if the line was not present
    :
fi

이 경우 일치하는 문자열은 리터럴이 아닌 RE로 처리됩니다.

답변2

사용행복하다(이전 Perl_6)

이 답변은 @roaima의 훌륭한 의견을 바탕으로 업데이트되었습니다.

다음 Raku 코드는 파일에서 정규식과 일치하는 줄이 몇 개나 발견되었는지 알려줍니다. given/mode는 when기본적으로 Raku의 "switch"(또는 "case") 문입니다. 일치하는 항목이 발견되면 변수 에 저장됩니다 $/(또는 ).$<>

~$ raku -e 'my regex RE { ^^ v \s disable $$ };
            given "/path/to/original.txt".IO.lines() {
                when $_.elems  > 0 and none / <RE> / { say "no match"; };
                when $_.elems == 1 and      / <RE> / { say "one line file, with match"; };
                when $_.elems  > 1 and      / <RE> / { say "multi-line file, with match"; };
                default {say  "error"; }
            };'

따라서 (예를 들어) when위의 세 번째 진술에서 ("일치하는 여러 줄 파일"), 블록 끝에 다음 코드를 추가할 수 있습니다 when.

#`(  
     spurt("/path/to/original_bak.txt", $_.subst(:global, "$/ "), createonly => True);
     unlink("/path/to/original.txt".IO) if "/path/to/original_bak.txt".IO  ~~ :e & :f;;
     copy("/path/to/original_bak.txt", "/path/to/original.txt", createonly => True)
  )  

위의 세 가지 파일 작업에 대한 오류 처리 기능이 내장되어 있습니다.스프레이,클래스 X::IO::링크 해제, 그리고클래스 X::IO::복사. 당신은 추가할 수 있습니다파일 테스트 연산자더 많은 측면을 테스트하기 위한 진술입니다.

spurt문은 새 _bak파일을 쓰고 unlink원본 파일의 연결을 해제한 다음 백업 파일을 원래 이름 copy으로 복사하고 두 개의 파일을 남깁니다. _bak여러 줄 주석 표시기(첫 번째 줄과 마지막 줄)를 제거하고 코드가 작동하고 있다고 만족하면 두 인스턴스를 모두 로 변경합니다(텍스트 반환 값으로 판단) createonly.False

당신은 다음과 같은 것을 할 수 있습니다"파일 한 줄, 일치"when또는 두 명령문을 하나로 결합 하도록 조건을 변경하면 됩니다 . 한 줄 형식이 마음에 들지 않으면 스크립트로 저장하고, 실행 가능하게 만들고, cron 작업으로 실행하는 등의 작업을 수행할 수 있습니다.


오류 처리를 수행하지 않는 이전 답변(Raku 및 Perl)은 다음과 같습니다.

행복하다: ~$ raku -ne '.put unless /^v\sdisable$/;' input.conf > tmp_input.conf

진주: ~$ perl -ne 'print unless /^v disable$/;' input.conf > tmp_input.conf

이 답변은 @Panki가 게시한 답변과 매우 유사하며 sedPerl/Raku가 생성된 빈 줄을 제거한다는 장점이 있습니다. Perl/Raku 차이점에 대한 설명은 아래 두 번째 링크를 참조하세요.

-iPerl은 "내부" 대체를 수행할 수 있지만 Raku는 수행할 수 없습니다. 그러나 Raku 제한을 우회하기 위해 쉘 리디렉션을 사용하도록 아래 세 번째 링크를 수정할 수 있습니다(어쨌든 먼저 백업을 만드십시오!).


참고: Raku는 편집에서 OP가 요청한 대로 POSIX를 준수하지 않습니다. POSIX가 아닌 접근 방식을 찾는 모든 사람에게 이 답변을 남깁니다.

https://docs.raku.org/언어/5to6-nutshell#given-when https://unix.stackexchange.com/a/749407/227738
https://unix.stackexchange.com/a/204378/227738
https://raku.org

관련 정보