たとえば、temp.txt
ファイルには、次のような情報が含まれています。
adsf on line jhkjhvjdbvjvbvbdjkvn
qerwtt on line fdgdgdgdd
qwqertg on line safffasffaf
wrt on line adaddsd
ファイルのすべての行でon line
をgrepして、行の残りの部分を別のファイルに書き込みます。つまり、temp.txt
ファイルでのプロセスの後、新しいファイルに次の内容を含める必要があります。
on line jhkjhvjdbvjvbvbdjkvn
on line fdgdgdgdd
on line safffasffaf
on line adaddsd
Linuxターミナルでそれを行うにはどうすればよいですか?
grep
の-o
オプションを使用して、目的の部分のみを選択します。この場合、パターンon line .*
を使用して、on line
から行の終わりまでの部分を選択します( s):
% grep -o 'on line .*' temp.txt >new.txt
% cat new.txt
on line jhkjhvjdbvjvbvbdjkvn
on line fdgdgdgdd
on line safffasffaf
on line adaddsd
この質問のvi
タグ、および POSIX準拠のex
コマンド を使用した自動ファイル編集が、このサイトと比較して短いドリフトを見つけたという事実を考えるとsed
、awk
、grep
、さらにはPerlに関する多くのアドバイスに、目的のフィルタリングを実行するPOSIX準拠のex
コマンドを次に示します。
_ex -sc 'g/.*\(on line\)/s//\1/ | .w!>>output
q!' input
_
コマンドに埋め込まれた改行に注意してください。これは、g
lobalコマンドを終了する他の明確な方法がないため、完全なPOSIX移植性のために必要です。ただし、mostの実装では複数の_-c
_コマンドを使用できます。その場合、次の1つのライナーはまったく同じように機能します。
_ex -sc 'g/.*\(on line\)/s//\1/ | .w!>>output' -c 'q!' input
_
このコマンドには、正規表現の魔法とex
- commandの魔法がたくさん含まれています。ex
はあまり知られていないようなので、各部分について説明します。
_-s
_はex
をサイレントモードで「バッチ処理の準備」で開始するため、何も端末に出力されません。
_-c
_は、「ファイルが開かれたときに次のコマンドを実行する」ことを意味します。 (input
は、開くファイルの名前です。)
ex
コマンド自体は、実際には2つのコマンドです。
_g/.*\(on line\)/s//\1/ | .w!>>output
q!
_
g
は「グローバル」コマンドであり、「指定した正規表現に一致するファイルのすべての行で次のコマンド(行の残りの部分)を実行する」を意味します。
与えられた正規表現は.*\(on line\)
であり、これは「0を含む任意の回数の文字に続けて「オンライン」」を意味します。括弧は、後でオンラインで参照するために「オンライン」でキャプチャするために使用されます。
実際には、g
コマンド自体も_g/on line/
_である可能性があり、同じように機能します。しかし、私が書いたs
ubstituteコマンドは、その正規表現にnothingを使用しています—_s//
_—これは、「最後に使用された正規表現を再利用する」ことを意味します。次に、s
コマンドは、置換テキストに_\1
_を使用します。この場合、「オンライン」を意味します。
ex
コマンドのパイプ記号_|
_は、シェルの場合のようにパイプを意味するものではありません。代わりに、それは通常個別のex
コマンドを区切るために使用され、それぞれが順番に、独立して実行されます。ただし、g
lobalコマンドはこれの例外です。グローバルコマンドでは、縦棒ですべてのコマンドが分離されますwithinグローバルコマンド、つまり、そのようなコマンドは実行されるだけです- regexに一致する行グローバルコマンドで指定されています。
垂直バーに続くコマンドは、この場合w
riteコマンドです。 「現在の行」を指定するドット_.
_が前に付きます。このアドレス指定子がない場合、書き込みコマンドは、現在の行が何であるかに関係なく、全体ファイルを書き込みます。 (グローバルコマンド内で書き込みコマンドを使用しているため、ドットを省略すると、書き込みコマンドはeach一致する行に置換コマンドが実行された後にファイル全体を書き込みます!)
_>>
_は、「ファイルがすでに存在する場合は、エラーを生成するのではなく、ファイルに追加する」ことを意味します。ファイルに複数回書き込むので、これは必要です。それ以外の場合は、出力ファイルに書き込まれたlast行のみで終わります。 _!
_の前の_>>
_は、「ファイルdoes n'tがすでに存在する場合、エラーをスローするのではなく、ファイルを作成してそこに書き込みます。」 (_!
_がないと、これが発生するかどうかはPOSIXで指定されていません。)もちろんoutput
は、書き込むファイルの名前です。
最後に、もちろん、_q!
_は「変更を現在のファイルに保存せずに終了する」ことを意味します。 input
ファイルの多くの行を置換しましたが、それらの変更を保存したくないので、_q!
_を使用します。
同等の他のいくつかのアプローチがあります。たとえば、次のとおりです。
_ex -sc '%s/.*\(on line\)/\1/e | v//d
w output | q!' input
_
しかし、これはe
フラグを置換コマンドに使用しますが、これはPOSIXにはありません。 (このフラグを省略した場合、ファイル内に正規表現.*\(on line\)
が見つからない場合、バッチ処理は停止します。)
もちろん、ex
really shinesはin-placeファイル編集にあります。しかし、上記のように、ファイルを別のファイルにフィルターするために使用することは確かに可能です。
これを試して:
grep -o 'on line .*' temp.txt > out.txt
-o
パラメータを指定すると、grepは行の一致する部分のみを出力します。これが必要です。
この例ではリモートまたはローカルでカールし、ローカルで.txtを印刷します
質問で述べられているようにデータが行ごとであり、データの最初の列に文字列「オンライン」を含まない場合。
curl file:///home/$USER/Public/input.txt | grep -o 'on line .*' > output.txt
または
curl https://yoursite.com/Public/input.txt | grep -o 'on line .*' > output.txt
これは現在のoutput.txtを上書きし、読み取り専用フォルダーを認識しません
grep
が-o
オプションをサポートしていない場合:
sed 's/^.*\(on line\)/\1/' temp.text > out.txt
または、on line
を含む行のみが必要な場合:
sed -n 's/^.*\(on line\)/\1/p' temp.text > out.txt
on line
が複数ある場合は、rightmostで始まる行の部分を出力します。左端の場合:
sed '/on line/!d;s//\
&/;s/.*\n//' temp.text > out.txt