¿Cómo buscar pestañas sin usar pestañas literales y por qué no funciona?

146

Cuando busco pestañas en un archivo con (e) grep, uso la pestaña literal ( ^v + <tab>). No puedo utilizar \tcomo reemplazo de pestañas en expresiones regulares. Con, por ejemplo, sed, esta expresión funciona muy bien.

Entonces, ¿hay alguna posibilidad de usar un reemplazo no literal <tab>y cuáles son los antecedentes de un trabajo / no interpretado \t?

Lasall
fuente
stackoverflow.com/questions/1825552/grep-a-tab-in-unix
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Respuestas:

206

grep está utilizando expresiones regulares según lo definido por POSIX . Por alguna razón POSIX no se ha definido \tcomo pestaña.

Tienes varias alternativas:

  • dile a grep que use las expresiones regulares definidas por perl (perl tiene \tcomo tabulador):

    grep -P "\t" foo.txt

    la página del manual advierte que esta es una característica "experimental". al menos \tparece funcionar bien. pero las características más avanzadas de perl regex pueden no ser

  • use printf para imprimir un carácter de tabulación para usted:

    grep "$(printf '\t')" foo.txt
  • usa el carácter de tabulación literal:

    grep "^V<tab>" foo.txt

    es decir: escriba grep ", luego presione ctrl+v, luego presione tab, luego escriba " foo.txt. Al presionar ctrl+vel terminal, la siguiente tecla se tomará al pie de la letra. eso significa que el terminal insertará un carácter de tabulación en lugar de activar alguna función vinculada a la tecla de tabulación.

  • use la función de cita ansi c de bash:

    grep $'\t' foo.txt

    Esto no funciona en todos los depósitos.

  • usa awk:

    awk '/\t/'
  • usar sed:

    sed -n '/\t/p'

Consulte el artículo de Wikipedia sobre expresiones regulares para obtener una descripción general de las clases de caracteres definidas en POSIX y otros sistemas.

lesmana
fuente
basándome en la respuesta de enzotib, permítanme agregar lo siguiente: grep $'\t' foo.txt(pero normalmente escribiría en fgreplugar de grep)
Walter Tross
Necesitaba esto, combinado con el uso del valor de una variable de entorno. He utilizado grep "$(printf '\t')${myvar}" foo.txt. Funcionó bien. Con algunos intentos, no pude conseguir que funcionara la última forma.
sancho.s
1
¿Hay alguna razón por la que plain grepno pueda interpretarse silenciosamente \tcomo tab? ¿POSIX requiere que eso \tsignifique algo más? ¿Quizás se supone que debe coincidir solo con un literal \ seguido de un t?
Aaron McDaid el
Quizás valga la pena señalar que BSD (incluido OSX) grep, carece de la opción -P.
TextGeek
Desde la página de manual This is highly experimental and grep -P may warn of unimplemented features.Probablemente no sea una buena idea para usar -Pen sistemas heredados. La printfelección es mejor
Avindra Goolcharan
13

Bash no es exactamente la respuesta que le gustaría escuchar, pero bash proporciona un posible uso de secuencias de escape

command | grep $'\t'

(¡no lo ponga entre comillas dobles!).

enzotib
fuente
1
no hay necesidad de -E (lo que se busca no es regex). Tampoco hay necesidad de canalizar desde un comando. Dicho esto, gracias por señalar esta característica bastante olvidada de bash (cadenas de comillas simples precedidas por $)
Walter Tross
2
De hecho, sugiero que @enzotib edite la respuesta para que sea simple grep $'\t'.
Teemu Leisti
Debería enfatizarse que esta es una característica de bash y que hará (¡en silencio!) Hacer lo incorrecto si es ejecutada por otro shell (como dash, que es el valor predeterminado para los scripts de shell en Ubuntu y otros)
xjcl
2

awk '/\t/' es mi solución favorita:

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

Salida: a\t.

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
fuente
1

Siempre se puede recurrir al uso del código hexadecimal ascii para la pestaña:

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

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

$ grep $'\x9' input.txt                                            
one two
Sergiy Kolodyazhnyy
fuente