와일드카드가 포함된 파이프 헤더 및 테일

와일드카드가 포함된 파이프 헤더 및 테일

같은 디렉토리에 여러 개의 파일이 있는데 15일부터 20일까지 연속적인 간격으로 특정 줄을 인쇄하고 싶습니다.

단일 파일의 경우 이는 작동 head -n20 file.txt | tail -n6하지만와일드카드 패턴으로 작동하게 하려면 어떻게 해야 하나요?, 예를 들어 해당 디렉토리의 모든 txt 파일에 대해 *.txt?

head -n20 *.txt | tail -n6 # this only crops results of head -n20

편집 1: 해결 방법도 알고 있지만 for와일드카드에서도 작동하는 통합된 방식으로 여러 작업에 대한 파이프라인을 정의하는 방법을 배우고 싶습니다.

ps에는 wildcards ==> file.txt <==와 결합할 때 제공되는 것과 같은 표준 헤더가 있을 수 있는데 , 이는 너무 많은 것을 요구합니다.headtail

pps는 우분투를 사용하지만 UNIX 전체 접근 방식이 더 좋습니다.

답변1

이 한 줄짜리는 어떻습니까?

for f in *.txt; do echo -e "\n==> $f <=="; head -n 20 "$f" | tail -n 6; done

현재 디렉터리에서 실행되면 glob을 .txt사용하여 *.txt모든 파일을 반복한 다음 헤더를 인쇄하고 각 파일에 대해 헤드 및 테일 작업을 수행합니다.

답변2

참고하시기 바랍니다.기준head여러 파일 이름을 인수로 사용하고 이러한 ==> filename <==헤더를 출력할 수 있습니다.기준tail하나의 파일 이름만 인수로 사용할 수 있습니다. 여러 파일 이름이 전달되면 동작이 지정되지 않습니다.

여기서는 쉘 루프 대신 다음 명령을 사용할 수 있습니다 gawk.

gawk 'BEGINFILE{print sep"==> "substr(FILENAME, 3)" <=="; sep = "\n"}
      FNR >= 15
      FNR == 20 {nextfile}' ./*.txt

이를 함수로 바꿀 수 있습니다:

linerange() (
  min=$1 max=$2
  shift 2
  exec gawk -v min="$min" -v max="$max" -e '
    BEGINFILE{print sep"==> "FILENAME" <=="; sep = "\n"}
    FNR > max {nextfile}
    FNR >= min' -E /dev/null "$@"
)

그런 다음:

linerange 15 20 *.txt

gawk, 다른 질문과 마찬가지로 awk양식의 매개변수는 var=value입력 파일 이름이 아닌 변수 할당으로 처리됩니다. 이는 일부 .txt파일이 제대로 작동하지 않는 경우( 또는 ... foo=bar.txt과 같은 더 짜증나는 부작용이 발생할 수 있음 )를 의미합니다.ARGC=0.txtORS=.txt

첫 번째 경우에는 접두사 ./(나중에 제거함)를 사용하여 이 문제를 해결하고 substr(FILENAME, 3), 두 번째 경우에는 (빈 파일: /dev/null을 전달하지만 -E매개변수를 사용할 때 할당이 처리되지 않습니다).-E

관련 정보