패턴 뒤가 아닌 라인에 대한 grep
특정 패턴을 따르지 않는 파일의 모든 줄을 찾으려고합니다.
한동안 history
GNU 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
, ...)?
답변
내가 이해 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
연속 된 동일한 행의 각 세트 중 하나만 인쇄하도록 작업해야합니다.
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"과 같은 두 개의 연속 된 대상 줄이 출력에 표시되지만 명확하지 않습니다. 입력 파일에 이러한 연속적인 행이 포함되면 나에게].