grep UNIX中的选项卡


417

如何grep在Unix平台上的文件中制表(\ t)?


53
只是使用grep "<Ctrl+V><TAB>",它的工作原理:(如果第一次类型grep ",然后按Ctrl + V组合键,然后按TAB键,然后输入"并按下回车键,瞧!)

16
ctrl + v是一个非常糟糕的想法!......是的,它可以从控制台命令工作,但它可能无法正常工作都键入一个脚本(你在编辑器的摆布,比如我使用mcedit和Ctrl + V不起作用那里)
THESorcerer


另请参阅:askubuntu.com/questions/53071/…(也在下面链接)
shiri

Answers:


374

如果使用GNU grep,则可以使用Perl样式的regexp:

grep -P '\t' *

它似乎与我的模式不符。尝试使用该语法不会打印任何内容。(Mac OS X变体是否不同?)
futureelite7 2010年

2
@futureelite:根据Apple的文档(developer.apple.com/Mac/library/documentation/Darwin/Reference/…),Mac OS X grep程序应支持-P选项。考虑在superuser.com上创建一个新问题。
放松

3
这对于GNU UNIX来说非常好,但是POSIX Solaris,AIX和HP-UX呢?那些对-P期权一无所知。

21
@rook GNU不是UNIX。
莉莉·钟

5
在Mac OSX上,你可以使用-e给予模式
费萨尔FEROZ

314

诀窍是在引号前使用$符号。它也适用于切割和其他工具。

grep $'\t' sample.txt

7
救生员提示可以挽救生命!据zsh我所知,它也可以正常工作。您能否评论该$符号的语义是什么?
罗曼(Romain)2012年

2
如果字符串包含'\ t'以外的任何内容,则无效。例如,您将如何搜索“ \ t”(制表符+空格)?
拉曼

6
拉曼:可以使用$'\t'' '。一个真实的示例显示它也可以与sh(不仅是bash,默认情况下未在Android上安装bash)一起使用busybox grep -oE '^nodev'$'\t''fuse$' /proc/filesystems
v6ak

5
我认为$'...'是个惯用语。可能不适用于sh。不知道关于csh或tcsh。
爱德华·福克

5
源自“ man bash”:特别对待$'string'形式的单词。该单词扩展为字符串,并按ANSI C标准的规定替换反斜杠转义字符。反斜杠转义序列(如果存在)将被解码...
broeni

84

我从未设法使grep使用'\ t'元字符。但是,我找到了两种替代解决方案:

  1. 使用<Ctrl-V> <TAB>(按Ctrl-V,然后键入tab)
  2. 使用awk: foo | awk '/\t/'

4
| awk '/\t/'解决方案将所有的炮弹,平台和系统的工作。
Samveen 2012年

6
+1用于便携式POSIX解决方案,不使用bashisms,zshism,GNUism和linuxisms。
詹斯(Jens)

1
如果要复制粘贴(从笔记或脚本),则ctrl-V没用。最好使用具有可见'\ t'的显式解决方案,在复制粘贴时,通常将文字TAB(即看起来像空白的TAB)转换为SPC ...
plijnzaad

awk在这里效果很好,但是在我的机器上使用非常大的文件进行的某些测试中,它比使用慢30%grep -P。根据用例,这可能是琐碎且无关紧要的,并且awk对于可读性和可移植性而言可能更好。
theferrit32

43

从Ask Ubuntu的以下答案中

告诉grep使用Perl定义的正则表达式(Perl具有 \tas标签):

grep -P "\t" <file name>

使用文字制表符:

grep "^V<tab>" <filename>

使用printf打印制表符给你:

grep "$(printf '\t')" <filename>


如果要复制粘贴(从笔记或脚本),则ctrl-V没用。最好使用具有可见“ \ t”的显式解决方案,在复制
粘贴

31

一种方法是(这与Bash一起使用)

grep -P '\t'

-P 启用Perl正则表达式,因此\ t将起作用。

正如用户放松所说,它可能特定于GNU grep。另一种方法是,如果外壳程序,编辑器或终端程序允许,则从字面上插入一个选项卡。


ksh shell中的未知P选项
Sachin Chourasiya

如放松所说,可能特定于GNU grep。刚刚澄清。
tjmoore

如何添加标签?当您按下Tab键时,它是否不启动自动完成过程?(这可能在bash脚本中起作用,但在命令行中
不起作用

1
如SamKrieg所述,@ AntonioCS为使Shell允许您键入任何字符,只需先键入CTRL-v。另请参见askubuntu.com/questions/53071/…–
丹尼斯·阿诺德

2
-P是特定于grep的,而不是任何shell的。-P应该可以在任何外壳中工作,前提是已安装GNU grep
plijnzaad

13

在表达式中直接插入制表符的另一种方法是使用$'\t'Bash中鲜为人知的引号:

grep $'foo\tbar'        # matches eg. 'foo<tab>bar'

(请注意,如果要匹配固定字符串,则可以在“ -F”模式下使用。)

有时使用变量可使符号更易读和易管理:

tab=$'\t'               # `tab=$(printf '\t')` in POSIX
id='[[:digit:]]\+'
name='[[:alpha:]_][[:alnum:]_-]*'
grep "$name$tab$id"     # matches eg. `bob2<tab>323`

10

这并不完全是您想要的,但可能适合您的情况

grep '[[:blank:]]'

相当于

grep -P '[ \t]'

因此它将找到Space和Tab。

§角色类别

请注意,它没有在我的中做广告man grep,但仍然有效

$ man grep | grep空白| 厕所
      0 0 0

@ A-letubby现在可以与编辑一起使用- -P已添加参数。
villapx

6

使用echo为您插入标签 grep "$(echo -e \\t)"


6

基本上有两种解决方法:

  1. 推荐)使用grep(1)支持的正则表达式语法。现代grep(1)支持POSIX 1003.2 regex语法的两种形式:基本(过时)RE和现代 RE。在re_format(7)和regex(7)手册页上分别详细描述了语法,它们分别是BSD和Linux系统的一部分。GNU grep(1)还支持pcre(3)库提供的与Perl兼容的RE。

    在正则表达式语言中,制表符通常由\tatom 编码。由BSD支持的原子扩展正则表达式(egrepgrep -E在BSD兼容系统),以及Perl兼容的RE(pcregrep,GNU grep -P)。

    基本的正则表达式和Linux扩展RE显然都不支持\t。请查阅UNIX实用程序手册页以了解它支持哪种正则表达式语言(因此sed(1),awk(1)和pcregrep(1)正则表达式之间的区别)。

    因此,在Linux上:

    $ grep -P '\t' FILE ...
    

    在类似BSD的系统上:

    $ egrep '\t' FILE ...
    $ grep -E '\t' FILE ...
    
  2. 将制表符传递到模式中。当您编辑脚本文件时,这很简单:

    # no tabs for Python please!
    grep -q '   ' *.py && exit 1
    

    但是,在交互式外壳中工作时,您可能需要依赖外壳和终端功能才能在行中键入正确的符号。在大多数终端上,这可以通过Ctrl+ V键组合来完成,该组合键指示终端按字面意义对待下一个输入字符(V“ verbatim”表示):

    $ grep '<Ctrl>+<V><TAB>' FILE ...
    

    某些外壳程序可能会提供命令排版的高级支持。这样的形式在bash(1)中的单词$'string'被特殊对待:

    bash$ grep $'\t' FILE ...
    

    但是请注意,尽管在命令行中比较友好,但是当脚本将被移动到另一个平台时,这可能会产生兼容性问题。另外,使用特价商品时请小心引号,有关详细信息,请咨询bash(1)。

    对于Bourne shell(不仅如此),可以使用由printf(1)增强的命令替换来模拟相同的行为,以构造适当的正则表达式:

    $ grep "`printf '\t'`" FILE ...
    


2

使用gawk,将字段定界符设置为制表符(\ t),然后检查字段数。如果大于1,则存在选项卡

awk -F"\t" 'NF>1' file

2
这有点矫kill过正,并且错过了问题。awk /\t/足以满足操作员的问题。
有限赎罪2012年

2

一个不错的选择是使用“ sed as grep”(如本经典sed教程中所述)。

sed -n 's/pattern/&/p' file

示例(适用于bash,sh,ksh,csh等):

[~]$ cat testfile
12 3
1 4 abc
xa      c
        a       c\2
1 23

[~]$ sed -n 's/\t/&/p' testfile 
xa      c
        a       c\2

[~]$ sed -n 's/\ta\t/&/p' testfile
        a       c\2

1

+1方式,适用于ksh,破折号等:使用printf插入TAB:

grep "$(printf 'BEGIN\tEND')" testfile.txt

在Ubuntu Trusty(Bash 4.3.11)上,这对我不起作用,但以下代码确实起作用:grep "$(printf '\t')" testfile.txt
Josh Rumbut 2015年

0

答案很简单。编写您的grep并在引号中输入tab键,至少在ksh中它能正常工作

grep "  " *

3
首先,您需要设法在shell中输入TAB字符-大多数shell将此键解释为命令(完成)
Kaii 2014年


0

使用'sed-as-grep'方法,但用个人喜好的可见字符替换选项卡是我最喜欢的方法,因为它清楚地显示了哪些文件包含所请求的信息,以及它们在行中的放置位置:

sed -n 's/\t/\*\*\*\*/g' file_name

如果您希望使用行/文件信息或其他grep选项,但又希望看到制表符的可见替换,则可以通过以下方法实现

grep -[options] -P '\t' file_name | sed 's/\t/\*\*\*\*/g'

举个例子:

$ echo "A\tB\nfoo\tbar" > test
$ grep -inH -P '\t' test | sed 's/\t/\*\*\*\*/g'
test:1:A****B
test:2:foo****bar

编辑:显然,以上内容仅适用于查看文件内容以定位选项卡-如果目标是将选项卡作为较大的脚本会话的一部分进行处理,则此功能无用。


0

这对于AIX很好。我正在搜索包含JOINED<\t>ACTIVE

voradmin cluster status | grep  JOINED$'\t'ACTIVE

 vorudb201   1       MEMBER(g) JOINED        ACTIVE
*vorucaf01   2       SECONDARY JOINED        ACTIVE


0

这些替代的二进制标识方法是完全可用的。而且,我真的很喜欢使用awk,因为我不太记得单个二进制字符的语法用法。但是,也应该可以以POSIX可移植的方式为shell变量分配一个值(即TAB = echo "@" | tr "\100" "\011"),然后以POSIX可移植的方式从那里随处使用它;以及(即grep“ $ TAB”文件名)。尽管此解决方案可以很好地与TAB一起使用,但是当在分配中使用另一个所需的二进制值(而不是TAB字符为'tr'的值)时,它也可以与其他二进制char一起使用。


0

其他答案中的$'\ t'表示法是特定于shell的-似乎可以在bash和zsh中使用,但不是通用的。

注意:以下内容适用于fishshell,不适用于bash

fish外壳中,可以使用未加引号的\t,例如:

grep \t foo.txt

或者可以使用十六进制或unicode表示法,例如:

grep \X09 foo.txt
grep \U0009 foo.txt

(这些符号对于更深奥的角色很有用)

由于这些值必须不带引号,因此可以通过串联将带引号和不带引号的值组合在一起:

grep "foo"\t"bar"

-4

您可以输入

grep \ t foo

要么

grep'\ t'foo

在文件foo中搜索制表符。您可能还可以执行其他转义代码,尽管我只测试了\ n。尽管这非常耗时,并且不清楚为什么要这样做,但是在zsh中,您还可以键入制表符,回到开头,grep并用引号将其引起来。


-6

查找空格多次[[:space:]] *

grep [[:space:]] *'。''。'

会发现这样的事情:

“标签” ..

这些是单引号('),而不是双引号(“)。
这就是在grep中进行串联的方式。=-)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.