텍스트 처리를 어떻게 해야 좋은 방법인지 잘 모르겠어서 여쭤보겠습니다.
다음 파일이 있습니다. ~/.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
플래그는 이를 반전시키므로 grep
RE와 일치하지 않는 모든 행은 성공한 것으로 간주됩니다. 이 경우 일치가 실패하는 유일한 경우 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가 게시한 답변과 매우 유사하며 sed
Perl/Raku가 생성된 빈 줄을 제거한다는 장점이 있습니다. Perl/Raku 차이점에 대한 설명은 아래 두 번째 링크를 참조하세요.
-i
Perl은 "내부" 대체를 수행할 수 있지만 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