sed は、多くのファイルから最初の行と最後の行を除くすべての行を削除します。

sed は、多くのファイルから最初の行と最後の行を除くすべての行を削除します。

1つのディレクトリにある多くの* .txtファイルを処理したいと思います。共通構造(区切られた共通ヘッダー)があります。しかし、1行あたりの行数はさまざまで、一部は1行、一部は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のみを保持します。

ファイルにデータ行が 1 つしか含まれていない場合、列 2 と 3 は 1 行に残ります。

ハハ、変だったけど本当に楽しかったです!

現在のディレクトリのデータファイル:

$ 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

ファイルの長さが1行だけの場合はループが必要です。とともにthrig のコマンド2回表示されます(試してみてください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 }
'

コードがより簡単になり、明確になり、メンテナンスが簡単になります。

関連情報