한 디렉터리에 있는 많은 *.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 }
'
코드가 더욱 단순해지고 명확해지며 유지 관리가 쉬워집니다.