패턴을 기반으로 행을 삭제하지만 처음 n개의 일치하는 행은 유지합니다.

패턴을 기반으로 행을 삭제하지만 처음 n개의 일치하는 행은 유지합니다.

패턴을 기반으로 텍스트 파일에서 줄을 삭제해야 하지만 처음 n 줄은 패턴과 일치하도록 유지해야 합니다.

입력하다

% 1 
% 2
% 3
% 4
% 5
text1
text2
text3

산출

%1
%2
text1
text2
text3

파일을 사용했지만 sed /^%/d%로 시작하는 모든 줄을 제거했는데 sed 3,/^%/d그것도 작동하지 않았습니다. 패턴의 처음 n개 행을 유지하고 나머지는 삭제해야 합니다.

답변1

% put으로 시작하는 모든 줄을 삭제하고 처음 두 줄의 입력을 유지하려면 다음을 수행하십시오.

sed -e 1,2b -e '/^%/d'

다음을 사용하는 것이 더 명확하지만 awk:

awk 'NR <= 2 || !/^%/'

또는 공연을 마친 후인 경우:

{ head -n 2; grep -v '^%'; } < input-file

입력의 첫 번째 줄이 아닐 수도 있는 처음 두 줄을 패턴과 일치하게 유지하려면 다음이 awk확실히 더 나은 옵션입니다.

awk '!/^%/ || ++n <= 2'

을 사용하려면 sed다음 기술을 사용할 수 있습니다.

sed -e '/^%/!b' -e 'x;/xx/{h;d;}' -e 's/^/x/;x'

즉, 예약된 공간을 이용하여 현재까지 일치하는 패턴의 발생 횟수를 센다. 효율적이지 않고 명확하지 않습니다.

답변2

이 작업을 혼자 수행하기에는 너무 간단할 것 같습니다 sed(불가능하지는 않지만 다소 복잡합니다. 예를 들어sed 푸시 박스무엇을 할 수 있는지).

어때요 awk?

#!/bin/awk -f
BEGIN { c = 0; }
{
    if (/^%/) {
        if (c++ < 3) {
            print;
        }
    } else {
        print;
    }
}

최신 BASH(정규 표현식 지원)를 사용할 수 있다면 위의 awk는 다음과 같이 번역될 수 있습니다.

#!/bin/bash -
c=0
while IFS= read -r line; do
    if [[ $line =~ ^% ]]; then
        if ((c++ < 3)); then
            printf '%s\n' "$line"
        fi
    else
        printf '%s\n' "$line"
    fi
done

패턴 일치를 위해 연산자 대신 sed또는를 사용할 수도 있습니다 .grep=~

답변3

진주한 줄해결책:

# in-place editing
perl -i -pe '$.>2 && s/^%.*//s' filename.txt

# print to the standard output
perl -ne '$.>2 && /^%/ || print' filename.txt

답변4

sed '/^%/{
3,$d}' '% 1 
% 2
% 3
% 4
% 5
text1
text2
text3'

불필요한 선을 제거하는 방법입니다.

편집: 내 대답은 s 와 동일한 조건에서 작동하며 Stephane Chazelas% 줄이 먼저 나오지 않으면 작동하지 않습니다.


너드 저격.

sed -n '/^% [^12]*$/!{
/^% [12][[:digit:]]\{1,\}/n
p}' file.txt

% number이는 스트림에서 문자열이 발견되는 위치 에 관계없이 작동합니다. %또는 이외의 문자 수로 시작하고 끝나는 줄은 무효화됩니다 . 주소는 사각지대를 제외하고는 모두 일치했습니다. 10-29 사이의 숫자는 계속 인쇄됩니다. 따라서 범위와 일치하도록 두 번째 주소를 중첩하고 줄을 건너뜁니다.12/% [A-Za-z3-9]*/

하지만 여전히 더 나을 것입니다.

관련 정보