단일 라인 매개변수를 기반으로 텍스트 파일에서 라인 추출

단일 라인 매개변수를 기반으로 텍스트 파일에서 라인 추출

저는 스크립팅을 처음 접했기 때문에 도움을 주시면 감사하겠습니다. 어떤 경우에는 상당히 길 수 있는 텍스트 파일이 있는데, 텍스트 줄의 각 부분 길이는 약 6/7줄입니다. 이는 로그 파일이며 각 섹션은 타임스탬프라는 단어로 시작됩니다. 각 줄 사이에는 빈 줄이 있습니다. 각 프로필 줄은 세미콜론으로 끝납니다.

timestamp=201706291035.....;
  line 2;
  line 3;
  line 4;
  line 5;
  line 6;
  line 7;

timestamp=201706291038.....;
  line 2;
  line 3;
  line 4;
  line 5;
  line 6;

한 줄의 각 섹션을 다른 텍스트 파일로 추출할 수 있어야 합니다. 마지막 세미콜론 없이 사용하는 것이 좋습니다.

timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7
timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6

이 정보가 해결책을 찾는 데 충분합니까?

다음은 간단한 예입니다.


타임 스탬프=2017-06-28-01.01.35.080576;
사용자 ID=user1
; 애플리케이션
ID=10.10.10.10.11111.12345678901;


타임 스탬프 = 2017-06-28-01.01.36.096486;
사용자 ID = user1
; 애플리케이션
ID = 10.10.10.10.11111.12345678901 ; table.field, table.field 여기서 table.field = 값


@steeldriver 스크립트를 실행한 후 소스 파일과 대상 파일이 동일하게 보입니다.

답변1

이는 다음과 같이 관용적 awk를 사용하여 수행할 수 있습니다.

awk '$1=$1' RS= OFS= infile

산출:

timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7;
timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6;

설명하다

여기에는 많은 것이 담겨 있습니다. 기본적으로 세 가지 단계가 있습니다.

  1. RS먼저, 입력은 레코드 구분 기호( )를 기준으로 레코드로 분할됩니다.
  2. 각 레코드는 필드 구분 기호( FS)를 기준으로 여러 필드로 분할됩니다.
  3. 인쇄할 때 출력 필드 구분 기호( OFS)가 필드 구분 기호로 사용됩니다.

awk가 입력을 구문 분석할 때 몇 가지 암시적 규칙이 적용됩니다. 데이터는 레코드별로 구분되어 한 번에 한 레코드씩 읽혀집니다 RS(기본값은 \n). RS위의 예와 같이 비어 있으면 빈 줄로 레코드가 구분됩니다. 따라서 각 부분은 레코드로 읽혀집니다.

강제 로 awk교체 하려면 첫 번째 필드를 그 자체로 설정합니다 .FSOFS$1

편집하다

지적한대로강철 드라이버, OP는 후행 세미콜론을 제거하려고 합니다. 뻔뻔한 표절:

awk '{ sub(/;$/,"",$NF); $1=$1 } 1' RS= OFS= infile

답변2

이는 다음을 통해 수행할 수 있습니다.

perl -lF';\n?' -00ne '$,=";"; print @F' yourfile

산출

timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7
timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6

피복재

  1. 펄 옵션

    a) -l=> ORS="\n" + RS = "\n"

    b) -F';\n?'=>는 FS를 세미콜론으로 만들고 그 뒤에 선택적 개행 문자가 옵니다.

    c) -00=>는 RS=를 만들어 단락 모드를 활성화합니다.

    d) -n=> 암시적 파일 읽기 + 명시적 인쇄가 활성화됩니다.

  2. 메인 : 현재 레코드에 따라 구분된 필드 $,=;인 OFS에 세미콜론이 추가됩니다 .@F$_FS

답변3

타임스탬프 앞에 빈 줄이 있으면 간단한

perl -pe 'chomp unless /^$/'

개행 문자가 없으면 이전 줄을 기억해야 합니다.

perl -pe 'chomp; print "\n" if $. > 1 && /^timestamp=/; print }{ print "\n"'

답변4

그냥 이런 방법이니까sed

이 문장을 출발점으로 삼으세요Peter Krumins의 Sed 전문 용어 설명, 1부: 파일 간격, 번호 매기기, 텍스트 변환 및 교체

  1. 행이 백슬래시 "\"로 끝나면 다음 행에 추가됩니다.

    sed -e :a -e '/\\$/N; s/\\\n//; ta'
    

첫 번째 표현식 ':a'는 이름이 지정된 레이블 "a"를 만듭니다. 두 번째 표현식은 현재 줄이 백슬래시 "\"로 끝나는지 확인합니다. 존재하는 경우 "N" 명령을 사용하여 다음 행과 연결됩니다. 그런 다음 "s/\\n//" 명령을 사용하여 연결 줄 사이의 슬래시와 줄 바꿈을 제거합니다. 교체가 성공하면 표현식의 시작 부분으로 분기하고 또 다른 백슬래시가 있을 수 있기를 바라면서 동일한 작업을 다시 수행합니다. 교체에 실패하면 줄이 백슬래시로 끝나지 않고 인쇄됩니다.

선행 공백을 유지하되 제거하기 위해 교체를 교체 하고 조정하면 \\다음과 같은 결과를 얻을 수 있습니다.;;

$ sed -e :a -e '/;$/N; s/\n *//; ta' infile
timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7;

timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6;

폐쇄! 이제 빈 줄을 짜내려고 합니다. 패턴을 테스트하여 이를 수행할 수 있습니다.마치다개행(즉, 추가된 행이 비어 있음)에서 다음과 같은 경우 인쇄합니다.에 따라개행 후 패턴 삭제:

$ sed -e :a -e '/;$/N; /\n$/{P;d;}; s/\n *//; ta' infile
timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7;
timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6;

이제 우리는 뒤에 오는 것들을 잘라내기만 하면 됩니다 ;. 이를 수행하는 한 가지 방법은 패턴 공간에 추가할 때 각 줄을 삭제한 ;다음 개행을 삭제하면서 다시 삽입하는 것입니다.

$ sed -e :a -e '/;$/{s///;N;}; /\n$/{P;d;}; s/\n */;/; ta' infile
timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7
timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6

우리가 이미 개행 문자를 먹었기 때문에 마지막 항목은 ;다시 삽입되지 않으므로 {P;d;}대체 항목이 s//\n /;/적용되지 않습니다.

관련 정보