web-dev-qa-db-ja.com

リテラルタブを使用せずにタブをgrepする方法と、なぜ\ tが機能しないのですか?

(e)grepを使用してファイル内のタブを検索するときは、litteralタブ(^v + <tab>)を使用します。 \tを正規表現のタブの代わりとして利用することはできません。例えばこの式は非常にうまく機能します。

それで、<tab>の非リターナル置換を使用する可能性はありますか?また、動作しない/解釈されない\tの背景は何ですか?

146
Lasall

grepは POSIX で定義された正規表現を使用しています。何らかの理由で、POSIXは\tをタブとして定義していません。

いくつかの選択肢があります:

  • perlで定義された正規表現を使用するようgrepに指示します(Perlにはタブとして\tがあります):

    grep -P "\t" foo.txt
    

    manページは、これが「実験的」機能であることを警告しています。少なくとも\tは正常に機能しているようです。しかし、より高度なPerl正規表現機能はそうではありません。

  • printfを使用して、タブ文字を印刷します。

    grep "$(printf '\t')" foo.txt
    
  • リテラルタブ文字を使用します。

    grep "^V<tab>" foo.txt
    

    つまり、grep "と入力してからctrl+vを押し、次にtabを押してから" foo.txtと入力します。ターミナルでctrl+vを押すと、次のキーが逐語的に取得されます。つまり、端末はタブキーにバインドされた何らかの機能をトリガーする代わりにタブ文字を挿入します。

  • ansi c quoting bashの機能を使用します。

    grep $'\t' foo.txt
    

    これはすべてのシェルで機能するわけではありません。

  • awkを使用します。

    awk '/\t/'
    
  • sedを使用します。

    sed -n '/\t/p'
    

POSIXおよびその他のシステムで定義されている文字クラスの概要については、 正規表現に関するウィキペディアの記事 を参照してください。

203
lesmana

それはあなたが聞きたいと思う答えそのものではありませんが、エスケープシーケンスの可能な使用はbashによって提供されます

command | grep $'\t'

(二重引用符で囲まないでください!)。

12
enzotib

awk '/\t/'は私のお気に入りの回避策です:

printf 'a\t\nb' | awk '/\t/'

出力:a\t

タブにはASCIIの16進コードを使用することに常に頼ることができます。

$ echo "one"$'\t'"two" > input.txt                                 

$ grep -P "\x9" input.txt                                          
one two

$ grep $'\x9' input.txt                                            
one two
1