助け合いフォーラム

LPIC

LPIC Lv1-101(Ver5.0)
問題ID : 3286
問題を開く
テキストファイル「file.txt」にある「PINGT」を「pingt」に変換して「hoge.txt」に保存したい。適切なコマンドは次のうちどれか。(全て選択)

正解

tr PINGT pingt < file.txt > hoge.txt

cat file.txt | tr PINGT pingt > hoge.txt

解説

指定した文字列を変換または削除するにはtrコマンドを利用します。
trコマンドは変換対象を標準入力からのみ受け付けます。つまり、変換・削除したい文字列が記載されているファイルをコマンドの引数として指定することが出来ません。そのため、以下のようにパイプ(|)やリダイレクト(<)を使用してtrの標準入力にファイルの内容を渡します。

cat ファイル名 | tr [オプション] [文字列1 [文字列2]]
または
tr [オプション] [文字列1 [文字列2]] < ファイル名

ただし、これだけでは変換結果がデフォルトの標準出力先であるディスプレイに表示されます。標準出力先をファイルに変更するには、リダイレクト記号の「>」を使用します。

したがって正解は
・tr PINGT pingt < file.txt > hoge.txt
・cat file.txt | tr PINGT pingt > hoge.txt
です。

以下は実行例です。


その他の選択肢については以下のとおりです。
・tr PINGT pingt | file.txt | hoge.txt
・file.txt | tr PINGT pingt
パイプは左のコマンドの標準出力を、次のコマンドの標準入力に送る記号ですので、誤りです。
「file.txt」「hoge.txt」がコマンドとみなされ、そのようなコマンドは存在しないというエラーになります。

・cat file.txt > tr PINGT pingt < hoge.txt
catコマンドの標準出力先が「tr」というファイルになります。trはファイルとみなされ、正常に動作しませんので、誤りです。

参考:
シェルは標準入力、標準出力および標準エラー出力の3つのストリームを制御することができます。


デフォルトで標準入力の入力元はキーボード、標準出力と標準エラー出力(エラーメッセージ)の出力先はディスプレイです。
また上図にある数字(0~2)はファイルディスクリプタと言い、それぞれ対応する入出力を表します。

リダイレクトという機能を使用する事で、入力元や出力先を変更できます。リダイレクトを使うには「>」や「<」などのリダイレクト演算子と、ファイルディスクリプタを組合せた記号を用います。その際、0と1のファイルディスクリプタは省略可能です。



例) コマンド < ファイル
ファイルの内容をコマンドの標準入力に送る

例) コマンド << 終了文字
終了文字が現れるまでコマンドの標準入力に入力を送る

例) コマンド > ファイル
コマンドの標準出力をファイルに出力 ( >> であればファイルに追記)

例) コマンド 2> ファイル
コマンドの標準エラー出力をファイルに出力( 2>> であればファイルに追記)

例) コマンド 1>&2
コマンドの標準出力の出力先を、標準エラー出力の出力先と同じにする(コマンドの正常な実行結果もエラーメッセージとしてディスプレイに表示する)

例) コマンド > ファイル 2>&1
コマンドの標準エラー出力の出力先を、標準出力の出力先と同じにする(例ではまず「>」で標準出力の出力先をファイルに変更しているので、標準エラー出力の出力先も同じファイルになる)

また、「パイプ(|)」という機能を使用することによって、標準出力に出力されたコマンドの実行結果を、別のコマンドの標準入力に渡すことが出来ます。


例) コマンド1 | コマンド2
コマンド1の標準出力をコマンド2の標準入力に送る
上に戻る

副作用のある正解

投稿日 2022/07/06

「PINGT」を「pingt」に変換

するためにtrコマンドを使っていますが,解説にある

tr [オプション] [文字列1 [文字列2]] < ファイル名

は間違いで,trの引数は文字列ではなく文字セットです.(manコマンドのSYNOPSISも tr [OPTION]... SET1 [SET2] となっています.)
trを使うと,確かに「PINGT」という文字列が「pingt」には変換されますが,それ以外のP,I,N,G,Tのすべての文字がp,i,n,g,tに置き換わってしまいます(副作用があります).

$ cat file.txt
PINGT
POINT
$ tr PINGT pingt < file.txt > hoge.txt
$ cat hoge.txt
pingt
pOint

そこで,正解としてはsedなどを使った以下のようなコマンドのほうが適切と考えます.

cat file.txt | sed s/PINGT/pingt/g > hoge.txt
sed s/PINGT/pingt/g < file.txt > hoge.txt
2022/07/07 00:28

そこで,正解としてはsedなどを使った以下のようなコマンドのほうが適切と考えます.

うーん、まぁそうかもしれませんがそれって選択肢の中にありませんよね?
trコマンドの学習のための問題に対して「tr以外の方法が適切」みたいな言及はちょっと違うかなーと思いました。


コメント

o ottijp

2022/07/07 00:48

なるほど.これが`tr`の学習問題なのであれば確かに`sed`を選択肢に入れるのは不適切ですね. 問題の区分が「ストリーム、パイプ、リダイレクトの使用」とあるので,`tr`に限定する必要はないのだと勘違いしていました. その場合は問題文を変えるほうがよいかもしれませんね.

この返信に対して
コメントを記入できます

この投稿に対して返信しませんか?