패턴 뒤가 아닌 라인에 대한 grep

Aug 17 2020

특정 패턴을 따르지 않는 파일의 모든 줄을 찾으려고합니다.

한동안 historyGNU bash(버전 4 및 5)를 사용하여 명령이 중복 되는 문제가 발생 했습니다. 나는 이것이 내 안에 .bashrc다음과 같은 줄이 있다는 사실 때문이라고 생각했습니다 .

 PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"

터미널 멀티플렉서 ( screen및 / 또는 tmux)를 사용하고 있기 때문에 위에서 언급 한 명령이 여러 번 실행됩니다 (따라서 echo $PROMPT_COMMAND결과는history -a; history -n; history -a; history -n;

일부 상황에서 (특히 다른 창 / 창 / 프레임 / 버퍼에서 작업을 동시에 수행 할 때) 입력 한 마지막 명령이 ~/.bash_history. 이로 인해 다음과 같은 항목이 발생했습니다.

#1596110297
yadm list -a | xargs -t ls -l
yadm list -a | xargs -t ls -l

말할 필요도없이 이것은 꽤 성가신 일입니다. 나는 (희망적으로) history-issue에 대한 수정 사항을 찾았 지만 (명령을으로 변경하여 PROMPT_COMMAND="history -a; history -n) 수정했습니다. 이것은 .NET 파일의 중복 항목으로 문제를 해결하지 못했습니다 history.

이제 중복 된 항목을 제거하고 싶습니다.

따라서 나는 현재 시작하는 #줄과 그 이후 한 줄을 제외한 모든 것을 표시하는 정규식을 찾으려고 합니다. 내 첫 번째 아이디어는 grep -v(선택을 반전 grep -A 1시키기 위해 )와 (일치하는 패턴 뒤에 추가로 한 줄을 얻기 위해 ) 결합하는 것이 었습니다 . 그러나

grep -v "^#" -A 1 ~/.bash_history

내가 원하는 결과를 얻지 못했습니다.

따라서 내 질문 : 누구든지 사용하는 방법에 대한 좋은 아이디어가 grep있습니까? 그렇지 않으면 : 어떻게이 다른 도구를 사용하여 수행 할 수있다 ( sed, awk, ...)?

답변

ilkkachu Aug 17 2020 at 03:48

내가 이해 grep -v "^#" -A 1하는 한 해시 기호로 시작하지 않는 줄과 각각 한 줄씩 인쇄하는 것을 의미합니다. 하지만 반대로 해시 기호로 시작 하는 줄과 그 뒤에 한 줄을 인쇄하고 싶지 않습니까?

테스트 파일이 주어지면 :

#123
echo this
echo this
#456
echo that
echo that
echo that
#789
echo third

grep -A1 ^# history.txt |grep -vxFe -- 인쇄물:

#123
echo this
#456
echo that
#789
echo third

두 번째 grep는 그룹 구분 기호 grep -A인쇄를 제거하는 것입니다 .

또는 uniq history.txt연속 된 동일한 행의 각 세트 중 하나만 인쇄하도록 작업해야합니다.

jubilatious1 Aug 17 2020 at 18:40

Raku 사용 (née Perl6)

이것은 여러 스크립팅 언어로 제공되는 "flip-flop"연산자의 작업처럼 보입니다. 다음은 Raku 프로그래밍 언어 (이전의 Perl6)를 사용한 답변입니다. 먼저보다 광범위한 테스트 파일을 작성하여 시작하십시오.

$ cat repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
B_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
D_yadm list -a | xargs -t ls -l
E_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
G_yadm list -a | xargs -t ls -l
H_yadm list -a | xargs -t ls -l
I_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5

이제 fff"sed와 같은"동작을 구현 하는 Raku의 플립 플롭 연산자를 사용하는 한 줄짜리 코드 입니다. 첫 번째 정규식이 ^^리터럴 "#"문자를 보는 줄 (줄 시작 부분)에 대해 캡처가 켜집니다 . ON되면 캡처는 첫 번째 정규식을 무시하고 두 번째 정규식에 대해 평가 ^^하여 "#"문자 가 누락 된 줄 (줄 시작 부분)과 일치하는 항목을 찾으면 해제됩니다 . 'negative'정규식은 <-[#]>음의 "Enumerated Character Class"이고 Raku 언어의 실제 기능인을 사용하여 아래 코드에서 구현 됩니다.

$ raku -ne '.put if /^^ "#" / fff /^^ <-[#]> /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5

실제로 첫 번째 정규식 ( fff중위 연산자 왼쪽에 있음)은 <+[#]>보다 병렬적인 구성을 위해 양의 "열거 형 문자 클래스"를 사용하여 작성할 수 있습니다 .

$ raku -ne '.put if /^^ <+[#]> / fff /^^ <-[#]> /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5

또한, 줄 시작 "#"다음에 하나 이상의 숫자가 따라 오도록 요구하여 정규식을 개선 할 수있는 것 같습니다. 즉 <digit>+, 아래를 참조하십시오.

$ raku -ne '.put if /^^ <+[#]> <digit>+ / fff /^^ <-[#]> <-digit>+ /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5

[위의 모든 코드는 B, D, E, G, H 및 I로 시작하는 중복 된 줄을 제거합니다. 내가 알아 차린 유일한 특이한 점은 "# 1596110297"과 같은 두 개의 연속 된 대상 줄이 출력에 표시되지만 명확하지 않습니다. 입력 파일에 이러한 연속적인 행이 포함되면 나에게].

https://raku.org/