ファイルの中身を1行ずつテキスト処理するには
Go言語 Java Scala PHP Python Ruby Perl sh
Go言語 (golang) 2015/06/18
Scanner
を使う例
import "bufio"
import "fmt"
import "os"
func main() {
var fp *os.File
var err error
if len(os.Args) < 2 {
fp = os.Stdin
} else {
fp, err = os.Open(os.Args[1])
if err != nil {
panic(err)
}
defer fp.Close()
}
scanner := bufio.NewScanner(fp)
for scanner.Scan() {
line := scanner.Text()
// lineはstring型で最後の改行が含まれない
fmt.Println(line)
}
}
ReadString
を使う例
package main
import "bufio"
import "fmt"
import "io"
import "os"
func main() {
var fp *os.File
var err error
if len(os.Args) < 2 {
fp = os.Stdin
} else {
fp, err = os.Open(os.Args[1])
if err != nil {
panic(err)
}
defer fp.Close()
}
reader := bufio.NewReader(fp)
for {
line, err := reader.ReadBytes('\n')
if err != nil && err != io.EOF {
panic(err)
}
// lineは[]byte型で最後の改行が含まれる
os.Stdout.Write(line)
if err == io.EOF {
break
}
}
}
Java 2013/10/08
例
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
while (true) {
String line = reader.readLine();
if (line == null)
break;
// line には最後の改行を含まない
...;
}
fclose(reader);
BufferedReader#readLine()
は "\n"
, "\r"
, "\r\n"
のいずれかを改行とみなす。
Scala 2016/12/21
Scalaの標準のライブラリを使う例
import scala.io.Source;
val source = Source.fromFile(filePath);
source.getLines.foreach { line =>
// line には最後の改行を含まない
...;
}
source.close();
ファイルではなく標準入力を行単位で処理するには
import scala.io.Source;
Source.fromInputStream(System.in).getLines.foreach { line =>
// line には最後の改行を含まない
...;
}
source.close();
scala.collection.Iterator
を自作する例
def stdinLineIterator(): Iterator[String] = {
var fp = new java.io.BufferedReader(new java.io.InputStreamReader(System.in, "UTF-8"));
var nextLine: String = null;
new Iterator[String] {
def hasNext: Boolean = {
if (fp == null) {
false;
} else {
if (nextLine == null) {
nextLine = fp.readLine;
}
if (nextLine == null) {
fp.close();
false;
} else {
true;
}
}
}
def next(): String = {
if (!hasNext) {
throw new java.util.NoSuchElementException();
}
val ret = nextLine;
nextLine = null;
ret;
}
}
}
この stdinLineIterator
が返す各行の文字列には最後の改行を含まない。
PHP 2017/02/27
例
$fh = fopen($filePath, 'r');
if ($fh) {
while (($line = fgets($fh)) !== false) {
// ファイルの最後が改行の場合、その改行を含む行がループの最後になる。
// $line には最後の改行を含む。
// 改行を削除
$line = preg_replace('/\r?\n?\z/', '', $line);
...;
}
fclose($fh);
}
fgets
は '\r'
(0x0D
) を改行としてみなさない。ただし auto_detect_line_endings
というPHPの設定値をphp.ini
ファイルまたはini_set
関数でonにした場合には 0x0D
も改行とみなされるらしい。
標準入力に対しては
$fh = fopen('php://stdin', 'r');
としてファイルポインタを取得するか、もしくはfopen
せずにファイルポインタを以下のように STDIN
と書けばよい。
while (!feof(STDIN)) {
$line = fgets(STDIN);
// $line には最後の改行を含む
...;
}
fgets
関数 | PHP Manual
http://php.net/manual/ja/function.fgets.php
auto_detect_line_endings
| PHP Manual
http://php.net/manual/ja/filesystem.configuration.php#ini.auto-detect-line-endings
Python 2014/07/02
例
for line in open(filePath):
# line には最後の改行を含む
line = line[:-1] # 最後の文字(改行かもしれない改行じゃないかもしれない)を取る
# line = line.rstrip() とすれば末尾の改行を含めた空白を削除する
Python2では以下のように xreadlines
メソッドを書いても同じ。
for line in open(filePath, 'r').xreadlines():
以下のように readlines
メソッドを書いてもループはできるが、この場合はループ開始時にいったんファイルの中身をすべて読み込んでしまうので、大きなファイルを扱うときにメモリを大量に消費する。
for line in open(filePath, 'r').readlines():
メソッドを書かない最初の例ではopen
メソッドが返すファイルオブジェクトがイテレータ型であることを利用している。イテレータ型であるのでリストの内包表記に使うこともできる。
lines = [line for line in open(filePath)]
標準入力から1行ずつ読み込む例
import sys
for line in sys.stdin:
# line には最後の改行を含む
...
Ruby 2014/12/30
例
IO.foreach(filePath) do |line|
...
end
または
open(filePath) do |fh|
fh.each do |line|
# line には最後の改行を含む
...
end
end
または
open(filePath) do |fh|
while line = fh.gets
# line には最後の改行を含む
...
end
end
標準入力から1行ずつ読み込む例
while line = STDIN.gets
# line には最後の改行を含む
...
end
Perl 2014/11/09
例
open(IN, '<', $filePath) or die "Cannot open";
while (my $line = <IN>) {
# $line には最後の改行を含む
...;
}
close IN;
または
open(IN, '<', $filePath) or die "Cannot open";
my @lines = <IN>;
# @lines には配列でファイル全体が保存されるので、あとで利用する
close IN;
while
文は修飾子の書き方もできるので、単純な処理であれば以下のような書き方も可能。
open(IN, '<', './hoge.txt') or die "Cannot open";
my $line;
print $line while $line = <IN>;
close IN;
またはさらに短縮して、
open(IN, '<', './hoge.txt') or die "Cannot open";
print $_ while <IN>;
close IN;
または
open(IN, '<', './hoge.txt') or die "Cannot open";
print while <IN>;
close IN;
open
せずに <IN>
の代わりに <STDIN>
と書けば、標準入力を1行ずつ処理できる。
sh (シェルスクリプト) 2016/06/23
シェルスクリプトでファイルから1行ずつ読み込んで、繰り返し処理させるには
read
というシェルの組み込みコマンドを使うとよい。
read
は標準入力から1行読み込んで変数に保存することができる。read 変数名
というふうに使う。
cat ./hoge.txt | while read line; do
# $line で各行の内容にアクセスできる
...
done
cat
の出力をパイプでwhile
文につなぐことで、
while
文の中にあるread
コマンドは ./hoge.txt
の内容を1行ずつ読み込める。
read
のあとにline
と指定しているので、読み込んだ内容は $line
という変数に保存される。
while
文は、入力の行数だけ繰り返す。途中に空行があっても問題ない。
ただし、この方法だとwhile
文がサブシェルの中で実行されるかもしれないので、
while
ループの中で変数に代入したり、exit
しようとしたりしてもうまくいかないかもしれない。ループの中の変数代入が、ループの外に反映されない、ということが起こる。
また、while
文の中で標準入力を受け取るコマンドがあると、cat ./hoge.txt
からの入力を消費してしまって、
read line
での読み込みが最初の1行しかできなくなってしまう。
ssh
コマンドでリモートホストでコマンドを実行させるときに、標準入力を消費しないつもりだったのに無意味に消費してしまっていることがよくある。そんなときは ssh -n ...
のように -n
をつける。
ループの中身をまるごと標準入力から隔離したい場合は、自分はよく以下のようにする。
cat ./hoge.txt | while read line; do (
# $line で各行の内容にアクセスできる
...
) </dev/null; done