Entfernen des ersten und des letzten Zeichens jeder Zeile aus der Befehlszeile

8

Ich versuche, das erste und das letzte Zeichen jeder Zeile in einer Textdatei zu entfernen und die resultierende abgeschnittene Version in einer neuen Datei zu speichern. Hat jemand eine Idee, wie man das effizient mit awkoder anderen Linux-Programmen / Befehlen speziell für große Dateien macht?

input.txt

(s,2,4,5,6)
"s,1,5,5,2"
{z,0,4,5,3}
[y,2,4,5,5]
(y,4,4,5,7)
(r,20,4,5,7)
(e,9,4,5,2)

Erwartete output.txt

s,2,4,5,6
s,1,5,5,2
z,0,4,5,3
y,2,4,5,5
y,4,4,5,79
r,20,4,5,7
e,9,4,5,2
Pacodelumberg
quelle

Antworten:

14

Ein anderer Weg nur zum Teufel:

rev input | cut -c2- | rev | cut -c2-

(Hinweis: Mit GNU cutfunktioniert es nur für Zeichen, die nur aus einem Byte bestehen (wie in Ihrem Beispiel).)

Drake Clarris
quelle
Nett! Dies ist deutlich schneller als die bisher vorgeschlagenen sed- und awk-Lösungen.
Gilles 'SO - hör auf böse zu sein'
Ich schlug diese Antwort für Leute vor, die Angst vor der sed / awk / regex-Syntax haben, hätte mir aber nicht vorgestellt, dass sie schneller ist, insbesondere bei großen Dateien, mit drei Pipes, die den gesamten Inhalt durchlaufen. Hätte gedacht, dass das Lesen einer Zeile zu einem bestimmten Zeitpunkt für große Dateien effizienter wäre.
Drake Clarris
3
Vermutlich erhalten Sie mehr als 40 Jahre Optimierung vieler dieser * nix-Dienstprogramme!
Drake Clarris
@ Gilles, es ist schneller, GNU in utf8-Gebietsschemas für einige Arten von Eingaben zu speichern, und es hängt davon ab, ob Sie die Wanduhrzeit oder die CPU-Zeit berücksichtigen. ssedoder die Heirloom-Werkzeugkiste sedkann eine bessere Leistung erzielen.
Stéphane Chazelas
@ Gilles Theres kein MAN-Eintrag für rev in Solaris 5.10. sed
Am
10

Löschen Sie gemäß Ihrer Frage das letzte und das erste Wort aus der Eingabedatei wie folgt:

sed 's/.$//; s/^.//' inputfile
Rahul Patil
quelle
Es wäre cool, wenn Sie diese mit der anderen Lösung vergleichen könnten s/.\(.*\).$/\1/. Es könnte schneller sein, weil keine Rückreferenzen verwendet werden, und in der Frage wurden "große Dateien" erwähnt.
10b0
4
@ l0b0 Ich habe mit getestet time yes | head -n 10000000 | COMMAND >/dev/null. Ich bekomme rev input | cut -c2- | rev | cut -c2-→ 0,14s, sed 's,.\(.*\).$,\1,'→ 3,38s; awk '{print substr($0,2,length()-2);}'→ 3,50 s; sed 's/.$//; s/^.//'→ 5.09s.
Gilles 'SO - hör auf böse zu sein'
@ Gilles +1 Das sollte eine Antwort sein.
10.
2
@ Gilles, das sind sehr kurze Zeilen. Ich finde, dass die Lösung von @ RahulPatil für 30 Zeichen breite Zeilen mit GNU sed dreimal so schnell ist wie die von @ juampa. Ebenfalls. sed 's/.\(.*\)./\1/'scheint schneller zu sein als sed 's/^.\(.*\).$/\1/'(GNU sed wieder). Außerdem hängt die Leistung vom Gebietsschema (Interpretation des Charakters) und der sedImplementierung ab (in dieser Hinsicht ist sed aus der Erbstück-Toolchest erheblich schneller als GNU sed).
Stéphane Chazelas
5

Wie immer gibt es viele Möglichkeiten

sed 's,.\(.*\).$,\1,g' your_file

Erläuterung

  • , - Das sed-Trennzeichen kann auch ein beliebiges anderes Zeichen sein, sofern es nicht benötigt wird, wo immer es benötigt wird.
  • . Ordnen Sie ein einzelnes Zeichen zu
  • \(.*\) - Gruppieren Sie den verbleibenden Teil, und dieser wird gespeichert, um weiter abgerufen zu werden.
  • . Ordnen Sie erneut ein einzelnes Zeichen zu
  • $ - Ende der Linie
  • \1 - Geben Sie den Text aus, der der obigen Gruppe entspricht
  • g global auf der Linie ersetzen.
jpmuc
quelle
2
Warum g? Es wird nur eine Übereinstimmung pro Zeile geben.
NJSG
Beachten Sie, dass nichts aus Zeilen mit weniger als 2 Zeichen entfernt wird.
Stéphane Chazelas
3

Sie können es auch tun, awkwenn Sie es vorziehen

awk '{print substr($0,2,length()-2);}' input.txt > output.txt
StrongBad
quelle
2
tr -d '()[]{}"' < your_file

Dies sollte auch funktionieren. Es "übersetzt" gut jedes der Zeichen in nichts (löschen).

Der Nachteil ist, dass sie gelöscht werden, wenn sie nicht auch das erste / letzte Zeichen sind. Es werden auch alle Endzeichen fehlen, die Sie nicht in der Liste auflisten ()[....

Mark Nichols
quelle