回答:
これを行うには多くの方法があります。
を使用してgrep
:
grep -E '^.{6,}$' file.txt >out.txt
これでout.txt
、6文字以上の行が含まれます。
逆の方法:
grep -vE '^.{,5}$' file.txt >out.txt
を使用してsed
、長さ5以下の行を削除します。
sed -r '/^.{,5}$/d' file.txt
長さ6以上の行を印刷する逆の方法:
sed -nr '/^.{6,}$/p' file.txt
の>
ような演算子を使用して出力を別のファイルに保存するgrep
か-i
、sed
次のオプションを使用してその場でファイルを編集できます。
sed -ri.bak '/^.{6,}$/' file.txt
元のファイルはとしてバックアップされfile.txt.bak
、変更されたファイルはとしてバックアップされますfile.txt
。
バックアップを保持したくない場合:
sed -ri '/^.{6,}$/' file.txt
シェルを使用して、遅い、これをしないでください、これは別の方法を示すためだけです:
while IFS= read -r line; do [ "${#line}" -ge 6 ] && echo "$line"; done <file.txt
使用してpython
、さらに遅いよりもgrep
、sed
:
#!/usr/bin/env python2
with open('file.txt') as f:
for line in f:
if len(line.rstrip('\n')) >= 6:
print line.rstrip('\n')
リスト内包表記を使用してPythonicにする方が良い:
#!/usr/bin/env python2
with open('file.txt') as f:
strip = str.rstrip
print '\n'.join([line for line in f if len(strip(line, '\n')) >= 6]).rstrip('\n')
とても簡単です:
grep ...... inputfile > resultfile #There are 6 dots
これは、非常に効率的でgrep
より多くのそれは必要以上に解析しようとはしません、またどのような方法で文字を解釈するために:それは単に(シェルは、その後resultfileにリダイレクト)標準出力に(全体)の行を送るとすぐにそれが6を見ましたその行の文字(.
正規表現コンテキストでは任意の1文字に一致します)。
そのため、grepは6文字以上の行のみを出力し、他の行はgrepによって出力されないため、結果ファイルになりません。
最速の方法:このCプログラムをコンパイルして実行します。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_BUFFER_SIZE 1000000
int main(int argc, char *argv[]) {
int length;
if(argc == 3)
length = atoi(argv[2]);
else
return 1;
FILE *file = fopen(argv[1], "r");
if(file != NULL) {
char line[MAX_BUFFER_SIZE];
while(fgets(line, sizeof line, file) != NULL) {
char *pos;
if((pos = strchr(line, '\n')) != NULL)
*pos = '\0';
if(strlen(line) >= length)
printf("%s\n", line);
}
fclose(file);
}
else {
perror(argv[1]);
return 1;
}
return 0;
}
でコンパイルしgcc program.c -o program
、./program file line_length
(ここでfile
=ファイルへのパスとline_length
=最小行の長さ、あなたの場合6
、最大行の長さは1000000
1行あたりの文字数に制限されます。これを変更するには、MAX_BUFFER_SIZE
)。
シェルソリューションを除く、この質問に対して提案された他のすべてのソリューションとの比較(8文字の平均長で10M行の〜91MBファイルでテストを実行):
time ./foo file 6
real 0m1.592s
user 0m0.712s
sys 0m0.160s
time grep ...... file
real 0m1.945s
user 0m0.912s
sys 0m0.176s
time grep -E '^.{6,}$'
real 0m2.178s
user 0m1.124s
sys 0m0.152s
time awk 'length>=6' file
real 0m2.261s
user 0m1.228s
sys 0m0.160s
time perl -lne 'length>=6&&print' file
real 0m4.252s
user 0m3.220s
sys 0m0.164s
sed -r '/^.{,5}$/d' file >out
real 0m7.947s
user 0m7.064s
sys 0m0.120s
./script.py >out
real 0m8.154s
user 0m7.184s
sys 0m0.164s
awk 'length>=6' file
length>=6
:length>=6
TRUEを返す場合、現在のレコードを印刷します。perl -lne 'length>=6&&print' file
lenght>=6
TRUEを返す場合、現在のレコードを印刷します。% cat file
a
bb
ccc
dddd
eeeee
ffffff
ggggggg
% ./foo file 6
ffffff
ggggggg
% awk 'length>=6' file
ffffff
ggggggg
% perl -lne 'length>=6&&print' file
ffffff
ggggggg
awk
解決を待っていた
sed
解決策を削除しなければなりませんでした(それは起こります)。XD-
pos
変数のポイントは何ですか?私はそれがline
改行文字で文字へのポインタを返しますが、あなたはそれを使用することはないようです。見つからない場合は、に等しく設定し\0
ます。
\0
(strchr()
文字が見つからない場合はNULLポインターを返します)。ポイントは、各行の終わりにある各改行をで置き換え\0
て、改行がカウントされないようにしますstrlen()
。これは、最後の行で改行が欠落している可能性に関係なく、長さを常に6と比較できるようにするためです。最後の行だけを別の方法で処理すると、はるかに効率的になります。おそらく後で更新します。
grep
同じファイルのソリューションを、それが実際に高速です(おそらくためには、strlen()
ここでは最高のアイデアではありません) 。getchar()
代わりに、最初のN文字のみをチェックするためにループを使用してみます。これにより、目に見える形で改善されるはずです。そして、はい、バッファーの長さを超える行はバッファーの長さに合わせて切り取られます。
Rubyソリューション:
$ cat input.txt
abcdef
abc
abcdefghijk
$ ruby -ne 'puts $_ if $_.chomp.length() >= 6 ' < input.txt
abcdef
abcdefghijk
シンプルなアイデア:ファイルをrubyのstdinにリダイレクトし、長さが6以上の場合にのみstdinから行を出力する