たとえば、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端末でこれをどのように実行できますか?
答え1
-o
オプションを使用grep
して必要な部分のみを選択してください。あなたの場合は、パターンを使用して行の先頭から行の終わりまでをon line .*
選択します。on line
% grep -o 'on line .*' temp.txt >new.txt
% cat new.txt
on line jhkjhvjdbvjvbvbdjkvn
on line fdgdgdgdd
on line safffasffaf
on line adaddsd
答え2
vi
この質問のタグと自動ファイル編集を見つけたという事実を考えると、POSIX 互換ex
コマンドsed
このサイトのアドバイスは、さらに Perl に対する膨大な量のアドバイスに比べてぬるま的です。awk
以下は、必要なフィルタリングを実行するPOSIX準拠のコマンドです。grep
ex
ex -sc 'g/.*\(on line\)/s//\1/ | .w!>>output
q!' input
g
コマンドに新しい行が含まれていることに注意してください。ただし、グローバルコマンドを終了する明示的な方法が他にないため、これは完全なPOSIX移植性に必要です。最大実装は複数の-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
私が書いた代替コマンドは以下を使用します。何もない正規表現の場合、s//
これは「最後に使用した正規表現の再使用」を意味します。次に、コマンドs
を使用して\1
テキストを置き換えます。この場合、「オンライン」を意味します。
|
コマンドのパイプシンボルは、ex
シェルのようにパイプを表しません。彼とは対照的に、通常別々の命令を分離するために使用され、ex
各命令は逐次的であるが独立して実行される。ただし、g
グローバルコマンドは例外です。グローバルコマンド内では、垂直バーがすべてのコマンドを区別します。以内にグローバルコマンド - つまり、そのコマンドのみを実行します。正規表現に一致する行でグローバルコマンドで指定されます。
この場合、垂直線の後の命令はw
儀式命令である。このアドレス指定子がない場合は、「現在行」を指定する点が前に続きます.
。書き込みコマンドは書き込みを実行します。みんなファイル、現在の行に関係なく。 (グローバルコマンドでwriteコマンドを使用するため、ドットを省略するとwriteコマンドが各一致する行には置換コマンドが実行されます。 )
これは>>
、「ファイルがすでに存在する場合はエラーを発生させるのではなく、ファイルに追加する」ことを意味します。ファイルに何度も書き込むため、これが必要です。それ以外の場合は、次のように終了します。最後出力ファイルに書き込む行です。!
上記の>>
意味は、「ファイルいいえすでに存在する場合は、エラーを発生させるのではなくファイルを生成し、そのファイルに書き込みます。 (そうでない場合、!
POSIXではこれが起こるかどうかは指定されません。)そしてもちろん、output
書き込むファイルの名前も同じです。
もちろん最後に、q!
「現在のファイルへの変更を保存せずに終了」を意味します。ファイルの複数行を置き換えましたが、input
これらの変更を保存したくないので、を使用してくださいq!
。
次のような他の同等の方法があります。
ex -sc '%s/.*\(on line\)/\1/e | v//d
w output | q!' input
ただし、これはe
POSIXでは利用できない代替コマンドのフラグを使用します。 (このフラグを省略すると、.*\(on line\)
ファイルに正規表現が見つからない場合はバッチ処理が停止します。)
もちろん、どこでex
本物シャインが入っています。所定の位置にファイルの編集。ただし、上記のように、あるファイルを別のファイルにフィルタリングするために確実に使用できます。
答え3
この試み:
grep -o 'on line .*' temp.txt > out.txt
この-o
パラメータを使用すると、grepは目的の行の一致する部分のみを出力します。
答え4
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
から始まる行の一部が印刷されます。一番右そんなことが起こる。一番左のアイテムの場合:
sed '/on line/!d;s//\
&/;s/.*\n//' temp.text > out.txt