Ich möchte wissen, wie man verwendet grep
, um alle Zeilen anzuzeigen, die mit demselben Zeichen beginnen und enden.
Ich möchte wissen, wie man verwendet grep
, um alle Zeilen anzuzeigen, die mit demselben Zeichen beginnen und enden.
Antworten:
POSIXly:
pattern='\(.\).*\1
.'
grep -x -- "$pattern" file
Es funktioniert nicht, wenn die Zeile mit einem ungültigen Bytezeichen beginnt oder endet. Wenn Sie diesen Fall abdecken möchten, können Sie hinzufügen LC_ALL=C
, obwohl dies nur LC_ALL=C
mit Einzelbyte-Zeichendaten funktioniert.
perl6
scheint das beste Werkzeug zu sein, wenn Sie es in Ihrer Box haben:
$ printf '\ue7\u301 blah \u107\u327\n121\n1\n123\n' |
perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
ḉ blah ḉ
121
1
Obwohl es immer noch an ungültigen Zeichen erstickt.
Beachten Sie, dass perl6
sich Ihr Text ändert, indem Sie ihn in eine NFC
Form verwandeln :
$ printf '\u0044\u0323\u0307\n' |
perl6 -pe '' |
perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+1e0c
U+0307
U+000a
$ printf '\u0044\u0323\u0307\n' |
perl -pe '' |
perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+0044
U+0323
U+0307
U+000a
Intern perl6
speichert Zeichenfolge in NFG
Form (steht für Normalization Form Grapheme
), die perl6
erfunden wurde, um mit nicht vorkomponierten Graphemen richtig umzugehen:
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.chars.say'
1
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.codes.say'
2
perl6
der Text dadurch geändert wird (drehen Sie ihn in NFC (Normalisierungsformular "zusammengesetzt")).
perl6
in NFG
Form ( G
für Grapheme
) gespeichert wird perl6
, um mit nicht vorkomponierten Graphemen richtig umzugehen.
Nicht grep aber awk:
awk -F "" 'NF && $1 == $NF'
Diese Sonderfälle werden behandelt:
Ein leerer FS teilt den Datensatz in ein Zeichen pro Feld gawk
, mawk
und busybox
awk
(Bytes, keine Zeichen für die letzteren zwei), ist aber nicht Standard und funktioniert nicht in den Implementierungen der awk
von der ursprünglichen , abgeleitet durch A, W und K wie auf BSDs und kommerziellen Einheiten. Tragbarer, aber mehr zu tippen:
awk '/./ && substr($0,1,1) == substr($0,length)'
FS
eine leere Zeichenfolge kein Standard ist und in einigen awk
Implementierungen nicht funktioniert .
awk 'length&&substr($0,1,1)==substr($0,length)'
(Standardargument von length
is beachten $0
und Standardaktion ist {print $0}
)
nawk
die fast genauso schlecht ist :-)
grep -xe '\(.\).*\1' -e .
Beispiel:
$ printf '%s\n' il y était cet été | grep -xe '\(.\).*\1' -e .
y
été
-x
ist für die genaue Übereinstimmung (Übereinstimmung auf der gesamten Linie). \1
als Rückverweis auf den in \(.\)
. Wir fügen ein hinzu -e .
, um den Sonderfall einer Zeile mit einem einzelnen Zeichen zu behandeln.
Es wird davon ausgegangen, dass die Eingabe gültigen Text im aktuellen Gebietsschema enthält.
Das Spiel ist auf Zeichen , nicht - Byte (die é in UTF-8 sind die zwei Bytes 0xC3 0xA9 zum Beispiel), noch Graphem - Cluster (es würde nicht funktionieren , wenn diejenigen E wurden in ihrem zerlegten Form geschrieben mit e
gefolgt von der U + 0301 zum Beispiel akuten Akzent kombinieren).
So arbeiten Sie an Graphemclustern mit einem grep
, der -P
PCRE unterstützt :
$ printf 'e\u0301te\u0301\n' | grep -xPe '(\X).*\1|\X'
été
Dies setzt voraus, dass die Zerlegung für die beiden Cluster gleich ist, zum Beispiel ein ḉ
Ausdruck, c
U+0301
U+0327
der nicht mit einem übereinstimmt, der als c
U+0327
U+0301
oder ć
( U+0107
) U+0327
oder ç
( U+00E7
) U+0301
oder ḉ ( U+1E09
) ausgedrückt wird . Dazu müssten Sie die Prüfung auf einem normalisierten Formular durchführen:
$ printf '\ue7\u301 blah \u107\u327\n' |
perl -MUnicode::Normalize -C -ne '
print if /^\X$/ || NFC($_) =~ /^(\X).*\1$/'
ḉ blah ḉ
perl6
, dann perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
sollten Sie alle Arbeiten für Sie erledigen.
Schnelle Python2-Alternative:
python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt
Beispiel:
$ python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt | cat -A
nathan$
ookie $
a line a$