sed는 많은 파일에서 첫 번째 줄과 마지막 줄을 제외한 모든 줄을 삭제합니다.

sed는 많은 파일에서 첫 번째 줄과 마지막 줄을 제외한 모든 줄을 삭제합니다.

한 디렉터리에 있는 많은 *.txt 파일을 처리하고 싶습니다. 공통 구조(구분된 공통 헤더)가 있습니다.하지만한 줄당 줄 수는 다양하며 일부는 한 줄이고 일부는 8줄에 달합니다.

각 파일의 첫 번째 줄과 마지막 줄을 제외한 모든 줄을 삭제하고 싶습니다. 유용한 조언이 있나요?

고쳐 쓰다:요청에 따라 몇 가지 테스트 데이터 파일을 제공했습니다.

stat87.txt

Stations_id; Stationshoehe; Geogr.Breite; Geogr.Laenge; von_datum; bis_datum; Stationsname;                                                                                                             
 87;     ; 46.1123;  8.5440;19010101;19661229;Dres

stat01.txt

Stations_id; Stationshoehe; Geogr.Breite; Geogr.Laenge; von_datum; bis_datum; Stationsname;                                                                                                             
 1;     ; 47.8400;  8.8500;18910101;19580228;Aach                                                                                                                                                   
 1;  478; 47.8413;  8.8493;19580301;19860630;Aach

예를 들어 stat56.txt입니다.

Stations_id; Stationshoehe; Geogr.Breite; Geogr.Laenge; von_datum; bis_datum; Stationsname;                                                                                                             
 56;     ; 46.4580;  7.6320;18980101;19450321;Hamb
 56;     ; 46.4580;  7.6320;19450321;19880511;Hamb                                                                                                                                                   
 56;  103; 46.4411;  7.6345;19880601;19990630;Hamb

이 경우 스테이션의 시간 범위를 캡처하기 위해 특히 열 5의 첫 번째 행과 열 6의 마지막 행을 유지하고 싶습니다.

결과:

find . -type f -name \*.txt -printf "%f\0" | xargs -0 -I xxxx sed -ni '
2 {
  $ {
    s/^[^;]*;[^;]*;[^;]*;[^;]*;\([^;]*\);\([^;]*\).*$/\1;\2/
    p
    q
  }
  s/^[^;]*;[^;]*;[^;]*;[^;]*;\([^;]*\).*$/\1/
  p
}
$ {
  s/^[^;]*;[^;]*;[^;]*;[^;]*;[^;]*;\([^;]*\).*$/\1/
  p
}' xxxx

생산하다....

19010101;19661229

18910101
19860630

18980101
19990630

그런 다음 간단한 sed 루프를 사용하여 ;를 추가하여 최종 파일을 정리했습니다.

'for file in *.txt; do
  sed 'N;s/\n/;/' "$file" > "cleaned$file"
 done'

19010101;19661229

18910101;19860630

18980101;19990630

답변1

완벽합니다. awk 버전은 다음과 같습니다.

find . -type f -name \*.txt -printf "%f\0" | xargs -0 -I xxxx sed -ni '
 2 {
   $ {
     s/^[^;]*;[^;]*;[^;]*;[^;]*;\([^;]*\);\([^;]*\).*$/\1;\2/
     p
     q
   }
   s/^[^;]*;[^;]*;[^;]*;[^;]*;\([^;]*\).*$/\1/
   h
 }
 $ {
   s/^[^;]*;[^;]*;[^;]*;[^;]*;[^;]*;\([^;]*\).*$/\1/
   H
   x
   s/\n/;/
   p
 }' xxxx

정말 유명한 분 감사합니다Sed - Bruce Barnett의 소개 및 튜토리얼

결과:

$ cat stat01.txt
18910101;19860630
$ cat stat56.txt
18980101;19990630
$ cat stat87.txt
19010101;19661229

----


참고용 첫 번째 버전

귀하의 의견을 바탕으로 데이터 파일 형식과 이를 처리할 sed 스크립트를 개발했습니다.

시도 해봐:

$ find . -type f -name \*.txt -printf "%f\0" | xargs -0 -I xxxx sed -ni '
 2 {
   $ {
     s/^[^;]*;\([^;]*\);\([^;]*\).*$/\1;\2/
     p
     q
   }
   s/^[^;]*;\([^;]*\).*$/\1/
   p
 }
 $ {
   s/^[^;]*;[^;]*;\([^;]*\).*$/\1/
   p
 }' xxxx

헤더가 포함된 첫 번째 줄을 제거합니다.

발견된 첫 번째 데이터 라인의 열 2와 파일의 마지막 데이터 라인의 열 3만 유지합니다.

파일에 데이터 행이 하나만 포함되어 있으면 열 2와 3이 한 행에 남습니다.

하하, 이상했지만 정말 즐거웠어요!

현재 디렉터리의 데이터 파일:

$ cat test01.txt
Name;Price;Amount;Description
Bread;2.1;3;healthy one
$ cat test02.txt
Name;Price;Amount;Description
Water;0.0;100;For life
Wine;10.3;1;Less than half a glass a day
$ cat test03.txt
Name;Price;Amount;Description
House;1000.0;1;home
Car;500.5;0;no need
Bike;10.3;5;Good for the planet and for me

결과:

$ cat test01.txt
2.1;3
$ cat test02.txt
0.0
1
$ cat test03.txt
1000.0
5

2개의 간략한 데이터 파일 내용과 예상 결과를 제공해 주시면 이 답변을 수정하겠습니다.

답변2

이렇게 하려면 파일을 반복해야 합니다.

for file in *.txt; do
  lines=$(wc -l < "$file")
  if [ "$lines" -lt 3 ]; then
    echo "$file is short enough, not touching it."
  else
    # for testing, you can also use the -i option
    sed -n '1p;$p' "$file" > "$file.new"
  fi
done

파일 길이가 한 줄뿐인 경우 루프가 필요합니다. 와 함께thrig가 내린 명령두 번 나타납니다(시도해 보세요 echo 1|sed -n '1p;$p').

답변3

이 작업에는 Gawk가 sed보다 더 나은 도구입니다. 원래 방법의 find-xargs 파이프라인을 재사용하고 동일한 출력 명명법을 사용합니다.

find . -type f -name \*.txt -printf "%f\0" | xargs -0 gawk -F\; '
    FNR==2  { von = $5 }
    ENDFILE { print von FS $6 > "cleaned" FILENAME }
'

코드가 더욱 단순해지고 명확해지며 유지 관리가 쉬워집니다.

관련 정보