助け合いフォーラム
LPIC Lv1-101(Ver5.0)
問題ID : 3688
問題を開く
Windowsのメモ帳で作成したテキストファイル「file1.txt」をLinuxで正しく扱うために、改行コードを変換して「file2.txt」として保存したい。適切なコマンドはどれか。(2つ選択)
正解
tr -d '^M' < file1.txt > file2.txt
sed s/^M//g file1.txt > file2.txt
解説
改行コードと代表的なOSの組み合わせは以下のとおりです。
・CRLF(\r\n):Windows
・LF(\n):Unix OS(Linux, Mac OS Xなど)
・CR(\r):古いMacOS(バージョン9まで)
上記の通りWindowsとLinuxでは改行コードが異なるため、テキストファイルの扱いが問題になる場合があります。CRLF(\r\n)からCR(\r)を取り除くことでLinuxの認識できる改行コード:LF(\n)のみにでき、正しく扱うことができるようになります。(類似問題ID:34286をご参照ください。)
また、CR(キャリッジリターン)は「^M」という制御コードでも表されるため、Windowsで作成したファイルをLinuxのエディタで開くと末尾に「^M」が表示されることがあります。よって、制御コード「^M」を取り除くことでもLinuxの改行コードLF(\n)に変換できます。
なお、Linux上で制御コード「^M」を入力するには、Ctrl+V、Ctrl+Mを続けて押下します。
選択肢を1つずつ確認してみます。
・tr -d '^M' < file1.txt > file2.txt
trコマンドの-dオプションで制御コード「^M」を削除しています。リダイレクト(<)によって「file1.txt」を入力とし、削除した結果を「file2.txt」に出力(>)しています。正しいコマンドです。
・tr -d 'CR' < file1.txt > file2.txt
「CR」という文字列を削除しているだけなので改行コードは変わりません。よって誤りです。
・sed s/^M//g file1.txt > file2.txt
sedコマンドで「file1.txt」中の全ての制御コード「^M」を空白文字に置換(つまり削除)して「file2.txt」に出力しています。正しいコマンドです。
・sed s//^M/g file1.txt > file2.txt
変換前の文字列が空白なのでエラーになります。よって誤りです。
・sed s/CRLF/LF/g file1.txt > file2.txt
全ての「CRLF」という文字列を「LF」という文字列に変換しているだけなので改行コードは変わりません。よって誤りです。
したがって正解は
・sed s/^M//g file1.txt > file2.txt
・tr -d '^M' < file1.txt > file2.txt
です。
以下は実行例です。
・CRLF(\r\n):Windows
・LF(\n):Unix OS(Linux, Mac OS Xなど)
・CR(\r):古いMacOS(バージョン9まで)
上記の通りWindowsとLinuxでは改行コードが異なるため、テキストファイルの扱いが問題になる場合があります。CRLF(\r\n)からCR(\r)を取り除くことでLinuxの認識できる改行コード:LF(\n)のみにでき、正しく扱うことができるようになります。(類似問題ID:34286をご参照ください。)
また、CR(キャリッジリターン)は「^M」という制御コードでも表されるため、Windowsで作成したファイルをLinuxのエディタで開くと末尾に「^M」が表示されることがあります。よって、制御コード「^M」を取り除くことでもLinuxの改行コードLF(\n)に変換できます。
なお、Linux上で制御コード「^M」を入力するには、Ctrl+V、Ctrl+Mを続けて押下します。
選択肢を1つずつ確認してみます。
・tr -d '^M' < file1.txt > file2.txt
trコマンドの-dオプションで制御コード「^M」を削除しています。リダイレクト(<)によって「file1.txt」を入力とし、削除した結果を「file2.txt」に出力(>)しています。正しいコマンドです。
・tr -d 'CR' < file1.txt > file2.txt
「CR」という文字列を削除しているだけなので改行コードは変わりません。よって誤りです。
・sed s/^M//g file1.txt > file2.txt
sedコマンドで「file1.txt」中の全ての制御コード「^M」を空白文字に置換(つまり削除)して「file2.txt」に出力しています。正しいコマンドです。
・sed s//^M/g file1.txt > file2.txt
変換前の文字列が空白なのでエラーになります。よって誤りです。
・sed s/CRLF/LF/g file1.txt > file2.txt
全ての「CRLF」という文字列を「LF」という文字列に変換しているだけなので改行コードは変わりません。よって誤りです。
したがって正解は
・sed s/^M//g file1.txt > file2.txt
・tr -d '^M' < file1.txt > file2.txt
です。
以下は実行例です。
![【図を表示】](https://ping-t-resouces.com/uploads/question_image/file/1889/k35714.jpg)
参考
正規表現とは、文字列の特定のパターンを認識する為に使用する表現方法です。文字列の検索や置換などを行う際に利用します。正規表現には基本正規表現(BRE: Basic Regular Expression)と拡張正規表現(ERE: Extended Regular Expression)があります。
以下は主な正規表現とその使用例をまとめたものです。
![【図を表示】](https://ping-t-resouces.com/uploads/question_image/file/1566/k34024.jpg)
正規表現には次のような基本の概念があります。
・特殊文字
「|」や「\(エスケープ文字)」などのように特殊な意味を持つ文字のことです。
・文字クラス
「[ ]」内の文字集合のことです。
・数量詞
「*」や「+」などのように直前の文字の繰り返し回数を示す文字のことです。
・アンカー
「^」や「$」などのように文字列内での位置を示す文字のことです。
なお、正規表現の「*」と、シェルによって解釈されるメタキャラクタの「*」では意味が異なるので注意してください。シェルは「*」を0文字以上の文字列と解釈します。
正規表現は明示的に「'」(シングルクォーテーション)や「"」(ダブルクォーテーション)の引用符で囲う事ができます。これらの引用符で囲まれた正規表現の記号は、シェルにメタキャラクタとして扱われなくなります。
正規表現を利用する主なコマンドは以下のとおりです。
・grep
ファイルや標準入力から、検索パターンにマッチする文字列を含む行を抽出するコマンド
なお、「-E」オプションを併用すると拡張正規表現が使えます(egrepコマンドと同様)。
・sed
ファイルや標準入力の内容を編集して表示するコマンド
例1)1から5までのいずれかの文字がある行を「test.txt」ファイルから抽出する場合
$ grep '[1-5]' test.txt
例2)「test.txt」ファイルの「#」から始まる行を削除して出力する場合
$ sed '/^#/d' test.txt
基本正規表現と拡張正規表現の違いに注意してください。grepコマンドは、-Eオプションを付けないと検索パターンを基本正規表現と判断しますので、上表の拡張正規表現が使えません。
実行例)
![【図を表示2】](https://ping-t-resouces.com/uploads/question_image/file/1567/kk34024.jpg)
基本正規表現では「?, +」は「\?, \+」とすることで、拡張正規表現と同様の意味を持つようになります。
![【図を表示3】](https://ping-t-resouces.com/uploads/question_image/file/1568/kkk34024.jpg)
以下は主な正規表現とその使用例をまとめたものです。
![【図を表示】](https://ping-t-resouces.com/uploads/question_image/file/1566/k34024.jpg)
正規表現には次のような基本の概念があります。
・特殊文字
「|」や「\(エスケープ文字)」などのように特殊な意味を持つ文字のことです。
・文字クラス
「[ ]」内の文字集合のことです。
・数量詞
「*」や「+」などのように直前の文字の繰り返し回数を示す文字のことです。
・アンカー
「^」や「$」などのように文字列内での位置を示す文字のことです。
なお、正規表現の「*」と、シェルによって解釈されるメタキャラクタの「*」では意味が異なるので注意してください。シェルは「*」を0文字以上の文字列と解釈します。
正規表現は明示的に「'」(シングルクォーテーション)や「"」(ダブルクォーテーション)の引用符で囲う事ができます。これらの引用符で囲まれた正規表現の記号は、シェルにメタキャラクタとして扱われなくなります。
正規表現を利用する主なコマンドは以下のとおりです。
・grep
ファイルや標準入力から、検索パターンにマッチする文字列を含む行を抽出するコマンド
なお、「-E」オプションを併用すると拡張正規表現が使えます(egrepコマンドと同様)。
・sed
ファイルや標準入力の内容を編集して表示するコマンド
例1)1から5までのいずれかの文字がある行を「test.txt」ファイルから抽出する場合
$ grep '[1-5]' test.txt
例2)「test.txt」ファイルの「#」から始まる行を削除して出力する場合
$ sed '/^#/d' test.txt
基本正規表現と拡張正規表現の違いに注意してください。grepコマンドは、-Eオプションを付けないと検索パターンを基本正規表現と判断しますので、上表の拡張正規表現が使えません。
実行例)
![【図を表示2】](https://ping-t-resouces.com/uploads/question_image/file/1567/kk34024.jpg)
基本正規表現では「?, +」は「\?, \+」とすることで、拡張正規表現と同様の意味を持つようになります。
![【図を表示3】](https://ping-t-resouces.com/uploads/question_image/file/1568/kkk34024.jpg)
sedコマンドについて
F
FMOURI
公開日 2023/02/21
sed s/^M//g file1.txt > file2.txt
が正解となっていますが、「s/^M//」の部分の「^」が正規表現により「行頭のM」という意味になるのでは?と思いました。
私はどのように間違っているのでしょうか?
2023/02/21 20:05
また、CR(キャリッジリターン)は「^M」という制御コードでも表されるため、Windowsで作成したファイルをLinuxのエディタで開くと末尾に「^M」が表示されることがあります。よって、制御コード「^M」を取り除くことでもLinuxの改行コードLF(\n)に変換できます。
なお、Linux上で制御コード「^M」を入力するには、Ctrl+V、Ctrl+Mを続けて押下します。
と解説にあるように、この^Mは「普通の文字^と普通の文字Mの並び」ではなく、「Ctrl+V, Ctrl+M で入力した制御コード」です。
制御コードは普通の文字ではないので、「行頭のM」という意味にはなりません。
制御コードのイメージがつかめない場合は、実環境で実際にCtrl+V, Ctrl+M で入力してみてください。
問題文に今回の^Mが制御コードであるということの説明はないのですが、文脈か消去法で理解する必要があります。
コメント
この投稿に対して返信しませんか?
F FMOURI
2023/02/21 19:19
従って、行末付近にある^Mは置換対象にならないのでは?と思いました