web-dev-qa-db-ja.com

ファイル内のすべての行をgrepし、パターンマッチングポイントからファイルに行を書き込みます。

たとえば、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ターミナルでそれを行うにはどうすればよいですか?

2
Navaneeth Cp

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
8
heemayl

この質問のviタグ、および POSIX準拠のexコマンド を使用した自動ファイル編集が、このサイトと比較して短いドリフトを見つけたという事実を考えるとsedawkgrep、さらにはPerlに関する多くのアドバイスに、目的のフィルタリングを実行するPOSIX準拠のexコマンドを次に示します。

_ex -sc 'g/.*\(on line\)/s//\1/ | .w!>>output
q!' input
_

コマンドに埋め込まれた改行に注意してください。これは、globalコマンドを終了する他の明確な方法がないため、完全な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/_である可能性があり、同じように機能します。しかし、私が書いたsubstituteコマンドは、その正規表現にnothingを使用しています—_s//_—これは、「最後に使用された正規表現を再利用する」ことを意味します。次に、sコマンドは、置換テキストに_\1_を使用します。この場合、「オンライン」を意味します。

exコマンドのパイプ記号_|_は、シェルの場合のようにパイプを意味するものではありません。代わりに、それは通常個別のexコマンドを区切るために使用され、それぞれが順番に、独立して実行されます。ただし、globalコマンドはこれの例外です。グローバルコマンドでは、縦棒ですべてのコマンドが分離されますwithinグローバルコマンド、つまり、そのようなコマンドは実行されるだけです- regexに一致する行グローバルコマンドで指定されています。

垂直バーに続くコマンドは、この場合writeコマンドです。 「現在の行」を指定するドット_._が前に付きます。このアドレス指定子がない場合、書き込みコマンドは、現在の行が何であるかに関係なく、全体ファイルを書き込みます。 (グローバルコマンド内で書き込みコマンドを使用しているため、ドットを省略すると、書き込みコマンドは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\)が見つからない場合、バッチ処理は停止します。)


もちろん、exreally shinesはin-placeファイル編集にあります。しかし、上記のように、ファイルを別のファイルにフィルターするために使用することは確かに可能です。

3
Wildcard

これを試して:

grep -o 'on line .*' temp.txt > out.txt

-oパラメータを指定すると、grepは行の一致する部分のみを出力します。これが必要です。

2
replay

この例ではリモートまたはローカルでカールし、ローカルで.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を上書きし、読み取り専用フォルダーを認識しません

0
Stef

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
0
Joseph R.