Bash : 파일에서 몇 줄을 가져 와서 다른 파일에 출력을 저장하는 방법 [닫힌]

Jan 17 2021

이와 같은 로그 파일이 있습니다.

$ cat build.log
..........
[ 60% 60917/101076] AAPT2 compile ....
[ 60% 60918/101076] AAPT2 compile ....
[ 60% 60919/101076] AAPT2 compile ....
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####

새 파일 로그의 출력이 다음과 같도록 구문 분석 된 새 로그처럼 생성하는 방법 :

$ cat parsed.log
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####

[ 60% 60920/101076]grep, sed 등을 사용하여 파일이 끝날 때까지 마지막 진행 상황 만 가져옵니다 . 감사합니다

답변

dawg Jan 17 2021 at 22:29

다음은 펄입니다.

$ perl -0777 -lne 'print $1 if /(^\[[^[]*\z)/m' file

또는 펄 파이프 :

$ perl -E 'say reverse <>' file | perl -lpE 'if (/^\[/){ say; last}' | perl -E 'say reverse <>'

를 들어 awk당신은 할 수 있습니다 :

$ awk 'BEGIN{RS="\\["}END{print "[" $0}' file

물론 실패가 항상 3 줄이면 가장 간단한 방법은 다음을 사용하는 것입니다 tail.

$ tail -n 3 file

모든 인쇄 :

[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
WilliamPursell Jan 17 2021 at 17:57
$ cat build.log ........ [ 60% 60917/101076] AAPT2 compile .... [ 60% 60918/101076] AAPT2 compile .... [ 60% 60919/101076] AAPT2 compile .... [ 60% 60920/101076] AAPT2 compile .... ninja: build stopped: subcommand failed. 21:41:22 ninja failed with: exit status 1 $ awk '$2 != n[2]{print p} {p = $0; split(p,n,FS)} END{print p}' build.log
........
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

awk이런 종류의 작업에 적합한 도구입니다. 여기에서 두 번째 필드가 이전 줄의 두 번째 필드와 일치하는지 확인하고 일치하면 인쇄합니다. 그런 다음 이전 줄을 저장하고 반복하십시오. 항상 입력의 마지막 줄을 인쇄하십시오.

potong Jan 17 2021 at 18:07

이것은 당신을 위해 일할 것입니다 (GNU sed) :

sed '/^\[/h;//!H;$!d;x' file

행이 시작 [되면 보류 공간에 저장합니다 (이전에 있던 항목을 덮어 씁니다).

그렇지 않으면 현재 행을 보류 공간에 추가하십시오.

마지막 줄을 제외한 모든 줄을 삭제합니다.

파일 끝에서 보류 공간으로 바꾸고 내용을 인쇄합니다.

IdrissNeumann Jan 17 2021 at 18:15

줄 순서를 변경하지 않고 이러한 종류의 필터를 수행하려는 경우 때때로 운이 좋지 않습니다. 그리고 그 라인이 파일의 시작에 서면, 또는 마지막에하지 않을 경우 : tac, sort그리고 uniq적절한 도구가 될하지 않을 것입니다.

다음을 사용하는 솔루션은 다음과 같습니다 awk.

$ awk 'function push(a,e) { a[length(a)+1] = e } BEGIN {split("", lines); to_replace="toreplace"; exists=0} {if ($0 ~ "^\\[ [0-9]+%"){ll=$0; if (exists <= 0) {exists++; push(lines,to_replace)}} else {push(lines, $0)}} END {for (e in lines){if (lines[e] == to_replace) {print ll} else {print lines[e]}}}' test.log 
..........
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####

읽을 수 있고 설명 된 버전 :

# a function to append an element to an array dynamically
function push(a,e) { 
  a[length(a)+1] = e 
} 

BEGIN {
  split("", lines); # initializing an array
  to_replace="toreplace"; # you can change the replace key if you want
  exists=0
} 

{
  if ($0 ~ "^\\[ [0-9]+%"){ # matching all percentages/progression lines, regardless of their values ll=$0; 
    if (exists <= 0) {
      exists++; 
      push(lines, to_replace)
    }
  } else {
    push(lines, $0)
  }
}

END {
  for (e in lines) {
    if (lines[e] == to_replace) {
      print ll
    } else {
      print lines[e]
    }
  }
}

William Pursel 솔루션 과의 차이점 은 백분율이 증가 할 때입니다. 이 경우 동작의 차이점을 살펴 보겠습니다.

$ cat test.log 
..........
[ 60% 60917/101076] AAPT2 compile ....
[ 60% 60918/101076] AAPT2 compile ....
[ 60% 60919/101076] AAPT2 compile ....
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####
$ awk 'function push(a,e) { a[length(a)+1] = e } BEGIN {split("", lines); to_replace="toreplace"; exists=0} {if ($0 ~ "^\\[ [0-9]+%"){ll=$0; if (exists <= 0) {exists++; push(lines,to_replace)}} else {push(lines, $0)}} END {for (e in lines){if (lines[e] == to_replace) {print ll} else {print lines[e]}}}' test.log 
..........
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####
$ awk '$2 != n[2]{print p} {p = $0; split(p,n,FS)} END{print p}' test.log 
..........
[ 60% 60919/101076] AAPT2 compile ....
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####

따라서 백분율이 동일하지 않더라도 마지막 진행 라인 만 유지하려는 경우 또는 동일한 백분율을 가진 라인 만 여러 번 필터링하려는 경우 선택할 수 있습니다.

Enlico Jan 17 2021 at 18:47

출력하려는 ​​첫 번째 줄이로 시작하는 마지막 줄인 것이 확실하다면 파일의 시작부터 줄 바꿈 [[선행 된 마지막 줄 까지 기본적으로 모든 것을 단일로 바꿉니다 [.

sed -z 's/.*\n\[/[/' file
EdMorton Jan 17 2021 at 22:50

...샘플 입력의 시작 부분에 있는 줄이 더 많은 선행 [...] ...줄을 나타낸다고 가정합니다 .

$ awk '/^\[/{p=$0 ORS; next} {print p $0; p=""}' build.log
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####

이 가정이 잘못된 경우 질문을 수정하여 s가 아닌 대표 값만 있는 최소한의 완전 하고 검증 가능한 예 를 표시하십시오 ....