回答:
次の正規表現を使用してみてくださいsed
。
sed '/^[0-9]*$/d' filename.txt
これにより、ファイルに数字のみが含まれる行が削除されます。
次のPerlスクリプトは、ファイルからn行目を削除しinput.txt
、残りをに出力しstdout
ます。行番号は次で指定できますline_numbers.txt
。
#!/usr/bin/perl
my @lines_to_exclude;
open(my $fh_line_numbers, "<", "line_numbers.txt") or die "Failed to open file: $!\n";
while(<$fh_line_numbers>) {
chomp;
push @lines_to_exclude, $_;
}
close $fh_line_numbers;
my $linecounter = 1;
open (my $fh_datafile, '<', 'input.txt') or die "Cannot open $filename: $!";
while ( my $line = <$fh_datafile> ) {
if ( ! ( $linecounter ~~ @lines_to_exclude ) ) {
print $line;
}
$linecounter++;
}
close($fh_datafile);
(~~
演算子はperl> = 5.10でのみ利用可能です)
すべての行番号をメモリに読み込むことがオプションである場合、次のようにしてこのようにすることができますawk
。
awk 'FNR == NR { h[$1]; next } !(FNR in h)' line-numbers.txt input.txt
使用可能なメモリが限られていて、line-numbers.txt
ファイルが数値でソートされている場合、次のようにできます。
delete-lines.awk
BEGIN {
lines_file = "line-numbers.txt"
if(!(getline n < lines_file)) {
print "Unable to open lines file " lines_file > "/dev/stderr"
exit
}
}
FNR != n
FNR == n {
getline n < lines_file
}
次のように実行します。
awk -f delete-lines.awk input.txt
次をline-numbers.txt
含む場所のテスト:
277
278
279
280
289
290
291
292
321
322
でinput.txt
表されseq 325
ます。
最初にメモリ内の行番号で:
seq 325 | awk 'FNR == NR { h[$1]; next } !(FNR in h)' line-numbers.txt -
次に、行番号を1つずつ読み取ります。
seq 325 | awk -f delete-lines.awk -
両方の場合の出力(1行目から274行目は省略):
.
.
.
275
276
281
282
283
284
285
286
287
288
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
323
324
325
試行2の追加コードを除いて、すべてのコードは実際にOPが要求したものとは反対のことに注意してください。試行2でわかるように、コマンドを簡単に調整できます。
サイズが約83 MBの1.108.752行のテキストファイルがありました。15行目から1.108.716行目までの46.744行を取得したかったのですが、これは平均で約24行ごとです。
2回目の試行は最初の試行よりも高速です。3番目は、少ない行でのみ機能します。
必要なすべての行についてsed
、テキストファイルの先頭から行を読み取りますが、印刷しません(-n
)。目的の行に到達したら、ファイルの最後まで読み込むのではなく、印刷(p
)してから終了(q
)します。その後、次の行番号に対してもう一度それを行います。
明らかに、これは毎回sed
よりも多くの行を通過する必要があるため、実行ごとに少し長くかかります。
私がその権利を計算した場合、私の場合、全体で307332472188パスがテキストファイルを通過します。ああ。
このアプローチでは、行番号のファイルでは行の順序は無関係です。
while read line; do
sed -n "${line}{p;q}" "${INFILE}"
done
タイミング結果:2568.80s user 256.10s system 92% cpu 51:00.37 total
。ダメ。
これはファイルから行番号を読み取り、p
(この行を印刷するために)を追加します。この文字列は、次にパイプされるsed
ファイル(から読み込む、-f
ここでれる)、STDIN
として書か-
れるたびに最初から出力され、sed
印刷される行番号は、実際には、。
sed 's/$/p/' "${LINENUMS}" | sed -n -f - "${INFILE}"
タイミング結果:146.54s user 0.18s system 100% cpu 2:26.70 total
。かなり良い!
あなたがしたい場合はありません(OPをやってみたかったような)linefileから行を印刷、linenumbersがされているように、わずかにコマンドを変更日間のではなく、eleted P rinted、および印刷他のすべての行を代わりに彼らに(-n)を削除:
sed 's/$/d/' "${LINENUMS}" | sed -f - "${INFILE}"
抽出したい行が多すぎたので、これはまったく役に立ちませんでした。ただし、(はるかに)少ない行で機能するはずですが、その制限がわかりません。
私はsedの長い文字列を作成しようとしましたが、これsed
はファイルを1回だけ通過することになります(!)、文字列の行番号以外を印刷しません:
sed -n "12p;15p;24p;345p;...;12345;" ${INFILE}"
しかし、その結果、420076
文字数についての文字列が生成され、sed
単純にに導かれsed: Argument list is too long
ます。これは理解できます。