Come posso grep
tab (\ t) nei file sulla piattaforma Unix?
Come posso grep
tab (\ t) nei file sulla piattaforma Unix?
Risposte:
Se usi GNU grep, puoi usare il regexp in stile Perl:
grep -P '\t' *
-P
dell'opzione.
Il trucco è usare il segno $ prima delle virgolette singole . Funziona anche per il taglio e altri strumenti.
grep $'\t' sample.txt
zsh
pure, per quanto ne so. Potresti commentare qual è la semantica di quel $
segno?
$'\t'' '
. Un vero esempio che mostra che funziona anche con sh (non solo bash, che non è installato di default su Android) è busybox grep -oE '^nodev'$'\t''fuse$' /proc/filesystems
.
Non sono mai riuscito a far funzionare il metacarattere "\ t" con grep. Tuttavia ho trovato due soluzioni alternative:
<Ctrl-V> <TAB>
(premendo Ctrl-V quindi digitando la scheda)foo | awk '/\t/'
| awk '/\t/'
soluzione funzionerà per tutte le shell, piattaforme e sistemi.
awk
funziona bene qui ma in alcuni test sulla mia macchina con file molto grandi è circa il 30% più lento rispetto all'utilizzo grep -P
. Questo potrebbe essere banale e irrilevante in base al caso d'uso e awk
potrebbe essere migliore semplicemente per leggibilità e portabilità.
Da questa risposta su Chiedi a Ubuntu:
Di 'a grep di usare le espressioni regolari come definite da Perl (Perl ha
\t
come tab):grep -P "\t" <file name>
Usa il carattere di tabulazione letterale:
grep "^V<tab>" <filename>
Uso
printf
per stampare un carattere di tabulazione per te:grep "$(printf '\t')" <filename>
Un modo è (questo è con Bash)
grep -P '\t'
-P
attiva le espressioni regolari Perl in modo che non funzionino.
Come utente rilassarsi dice, può essere specifico per GNU grep. L'alternativa è quella di inserire letteralmente una scheda se la shell, l'editor o il terminale lo consentono.
Un altro modo per inserire la scheda letteralmente all'interno dell'espressione è usare la $'\t'
citazione meno conosciuta in Bash:
grep $'foo\tbar' # matches eg. 'foo<tab>bar'
(Nota che se cerchi corrispondenze per stringhe fisse puoi usarlo con la modalità '-F'.)
A volte l'uso delle variabili può rendere la notazione un po 'più leggibile e gestibile:
tab=$'\t' # `tab=$(printf '\t')` in POSIX
id='[[:digit:]]\+'
name='[[:alpha:]_][[:alnum:]_-]*'
grep "$name$tab$id" # matches eg. `bob2<tab>323`
Questo non è esattamente quello che stai cercando, ma potrebbe funzionare nel tuo caso
grep '[[:blank:]]'
Equivalente a
grep -P '[ \t]'
Quindi troverà spazio e tabulazione.
Nota, non è pubblicizzato nel mio man grep
, ma funziona ancora
$ man grep | grep vuoto | bagno 0 0 0
-P
argomento è stato aggiunto.
Esistono sostanzialmente due modi per affrontarlo:
( Consigliato ) Usa la sintassi delle espressioni regolari supportata da grep (1). Modern grep (1) supporta due forme di sintassi regex POSIX 1003.2: RE di base (obsolete) e moderne RE . La sintassi è descritta in dettaglio nelle pagine man re_format (7) e regex (7) che fanno parte rispettivamente dei sistemi BSD e Linux. GNU grep (1) supporta anche RE compatibili con Perl come fornito dalla libreria pcre (3).
Nel linguaggio regex il simbolo della scheda è generalmente codificato \t
dall'atomo. L'atomo è supportato da espressioni regolari estese BSD ( egrep
, grep -E
su sistemi compatibili BSD), nonché da RE compatibili Perl ( pcregrep
, GNU grep -P
).
Sia le espressioni regolari di base che le RE estese di Linux sembrano non avere supporto per \t
. Consultare la pagina man dell'utilità UNIX per sapere quale linguaggio regex supporta (da qui la differenza tra espressioni regolari sed (1), awk (1) e pcregrep (1)).
Pertanto, su Linux:
$ grep -P '\t' FILE ...
Su sistemi simili a BSD:
$ egrep '\t' FILE ...
$ grep -E '\t' FILE ...
Passa il carattere di tabulazione nel modello. Questo è semplice quando si modifica un file di script:
# no tabs for Python please!
grep -q ' ' *.py && exit 1
Tuttavia, quando si lavora in una shell interattiva, potrebbe essere necessario fare affidamento sulle funzionalità della shell e del terminale per digitare il simbolo corretto nella riga. Sulla maggior parte dei terminali questo può essere fatto attraverso la combinazione di tasti Ctrl
+ V
che indica al terminale di trattare letteralmente il carattere di input successivo (il termine V
è "alla lettera"):
$ grep '<Ctrl>+<V><TAB>' FILE ...
Alcune shell possono offrire supporto avanzato per la composizione dei comandi. Tale, in bash (1) le parole del modulo $'string'
sono trattate appositamente:
bash$ grep $'\t' FILE ...
Si noti tuttavia che, sebbene sia utile nella riga di comando, ciò può causare problemi di compatibilità quando lo script verrà spostato su un'altra piattaforma. Inoltre, fai attenzione con le virgolette quando usi le offerte speciali, consulta bash (1) per i dettagli.
Per Bourne shell (e non solo) lo stesso comportamento può essere emulato usando la sostituzione di comando aumentata da printf (1) per costruire il regex corretto:
$ grep "`printf '\t'`" FILE ...
usa gawk, imposta il delimitatore di campo su tab (\ t) e controlla il numero di campi. Se più di 1, allora ci sono / sono le schede
awk -F"\t" 'NF>1' file
awk /\t/
è sufficiente per la domanda dell'op.
Una buona scelta è usare 'sed as grep' (come spiegato in questo classico tutorial di sed ).
sed -n 's/pattern/&/p' file
Esempi (funziona in 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
Modo +1, che funziona in ksh, trattino, ecc: usa printf per inserire TAB:
grep "$(printf 'BEGIN\tEND')" testfile.txt
grep "$(printf '\t')" testfile.txt
La risposta è più semplice Scrivi il tuo grep e nella virgoletta digita il tasto tab, funziona bene almeno in ksh
grep " " *
L'uso del metodo 'sed-as-grep', ma la sostituzione delle schede con un carattere visibile di preferenza personale è il mio metodo preferito, in quanto mostra chiaramente sia quali file contengono le informazioni richieste, sia anche dove sono posizionate all'interno delle linee:
sed -n 's/\t/\*\*\*\*/g' file_name
Se desideri utilizzare le informazioni sulla linea / sul file o altre opzioni grep, ma vuoi anche vedere il rimpiazzo visibile per il carattere della scheda, puoi farlo da
grep -[options] -P '\t' file_name | sed 's/\t/\*\*\*\*/g'
Come esempio:
$ echo "A\tB\nfoo\tbar" > test
$ grep -inH -P '\t' test | sed 's/\t/\*\*\*\*/g'
test:1:A****B
test:2:foo****bar
EDIT: Ovviamente quanto sopra è utile solo per visualizzare i contenuti dei file per individuare le schede --- se l'obiettivo è gestire le schede come parte di una sessione di scripting più ampia, questo non ha alcuno scopo utile.
Potresti voler usare grep "$(echo -e '\t')"
L'unico requisito è echo
essere in grado di interpretare le fughe di backslash.
Questi metodi di identificazione binaria alternativi sono totalmente funzionali. E, mi piace molto quello che usa awk, poiché non ricordo del tutto l'uso della sintassi con singoli caratteri binari. Tuttavia, dovrebbe anche essere possibile assegnare a una variabile shell un valore in modo portatile POSIX (cioè TAB = echo "@" | tr "\100" "\011"
), e quindi impiegarlo da lì ovunque, in modo portatile POSIX; anche (es. grep "$ TAB" nomefile). Mentre questa soluzione funziona bene con TAB, funzionerà bene anche con altri caratteri binari, quando nell'assegnazione viene utilizzato un altro valore binario desiderato (anziché il valore per il carattere TAB su 'tr').
La notazione $ '\ t' fornita in altre risposte è specifica della shell - sembra funzionare in bash e zsh ma non è universale.
NOTA: quanto segue è per la fish
shell e non funziona in bash :
Nella fish
shell, si può usare un non quotato \t
, ad esempio:
grep \t foo.txt
Oppure si possono usare le notazioni esadecimali o unicode, ad esempio:
grep \X09 foo.txt
grep \U0009 foo.txt
(queste notazioni sono utili per caratteri più esoterici)
Poiché questi valori devono essere non quotati, è possibile combinare i valori quotati e non quotati mediante concatenazione:
grep "foo"\t"bar"
Puoi digitare
grep \ t foo
grep '\ t' pippo
per cercare il carattere di tabulazione nel file pippo. Probabilmente puoi anche fare altri codici di escape, anche se ho testato solo \ n. Sebbene sia piuttosto dispendioso in termini di tempo e non sia chiaro il motivo per cui vorresti, in zsh puoi anche digitare il carattere della scheda, tornare all'inizio, grep e racchiudere la scheda tra virgolette.
Cerca spazi vuoti più volte [[: space:]] *
grep [[: space:]] * '.' '.'
Troverà qualcosa del genere:
'la scheda' ..
Queste sono virgolette singole (') e non doppie (").
Ecco come concatenare in grep. = -)
grep "<Ctrl+V><TAB>"
, funziona (se la prima volta: digitagrep "
quindi premi Ctrl + tasto V combinato, quindi premi il tasto TAB, quindi digita"
e premi invio, voilà!)