Kann beim Ausschneiden nur der erste Buchstabe nach einem Komma und einem Leerzeichen beibehalten werden?

Kann beim Ausschneiden nur der erste Buchstabe nach einem Komma und einem Leerzeichen beibehalten werden?

Ich habe eine Eingabe, die so aussieht:

Austin, Ashley D
Bender, Isaiah J

Hier versuche ich, den Vornamen bis zum "," zu kürzen und dann den ersten Buchstaben des zweiten Vornamens hinzuzufügen.

Die beiden oben genannten wären beispielsweise Austina und Benderi. Kann mir bitte jemand helfen?

Antwort1

Sie haben Interesse bekundet, dieses Problem mit zu lösen cut. Es sollte eine Möglichkeit geben, dies mit zu tunRohreund eine Kombination auscut,tr, und vielleicht)paste. Aber insbesondere, da Sie die Schreibweise des Anfangsbuchstabens ändern (z. B. wird das führende „A“ in Ashley zum nachfolgenden „a“ in „Austina“), ist es einfacher, etwas Vielseitigeres als zu verwenden cut. Ich schlage vorein Perl-Einzeiler, das könnte dies oder etwas Ähnliches sein, abhängig in erster Linie davon, welche Zeichen Sie in Namen zulassen möchten:

perl -wpe 's/^(\w+),\s*(\w).*/$1\L$2/' file

Dadurch wird der Perl-Interpreter mit aktivierten Warnungen ( -w) ausgeführt, die Eingabe zeilenweise gelesen, in jeder Zeile ein Skript ausgeführt und das Ergebnis ausgegeben ( -p) und das Skript aus dem nächsten Befehlszeilenargument übernommen ( -e). Das Skript selbst, s/^(\w+),\s*(\w).*/$1\L$2/, das ichZitatmitEinzelzitateso dass die Shell nicht ihre eigeneErweiterungenbesteht aus einem Ausdruck, der seine Eingabe anpassts/pattern/replacement/Musterund ersetzt das Match durchErsatz.

Imregulären Ausdruck, ^(\w+),\s*(\w).*:

  • ^entspricht dem Anfang einer Zeile.
  • (\w+)entspricht einem oder mehreren (+) Wortzeichen (\w, siehe unten) und fängt sie ein (( )) in die erste Erfassungsgruppe.
  • ,entspricht wörtlich sich selbst.
  • \s*entspricht null oder mehr (*) Leerzeichen (\s).
  • (\w)entspricht genau einem Wortzeichen (\w, siehe unten) und fängt es ein (( )) in die zweite Erfassungsgruppe.
  • .* entspricht null oder mehr (*) eines beliebigen Zeichens, das in einer Zeile erscheinen kann (.). Mit anderen Worten, es stimmt mit dem Rest der Zeile überein.

Dann $1\L$2bewirkt der gesamte übereinstimmende Text (die ganze Zeile, vorausgesetzt, estatÜbereinstimmung) zu ersetzen durch:

  • $1, der Inhalt der ersten Erfassungsgruppe, ohne Änderungen. Dies ist das Feld, das den Nachnamen einer Person enthalten soll.
  • \L$2, der Inhalt der zweiten Erfassungsgruppe ( $2), umgewandelt in Kleinbuchstaben (\L). Dies ist das erste Zeichen, das den Vornamen einer Person enthalten soll (jedoch in Kleinbuchstaben).

Das mag für Sie so gut funktionieren. Aber:

  • \wJe nachdem, welche Zeichen in Namen übereinstimmen sollen, müssen Sie möglicherweise beide Vorkommen von im Muster ändern . \wstimmt nur mit Buchstaben, Ziffern und dem Unterstrich ( _) überein. Viele Namen enthalten andere Zeichen als dieses, z. B. Bindestriche und Apostrophe.
  • Es stellt sich auch die Frage, was als Buchstabe gilt (was, wenn auch manchmal mit unterschiedlichen Lösungen, auch für einfachere Werkzeuge gilt). SieheWas ist die beste Möglichkeit, in einem regulären Ausdruck nur Buchstaben abzugleichen?Dies ist relevant für Namen, die Buchstaben mit Akzent, an Buchstaben angehängte diakritische Zeichen und Buchstaben in nicht-lateinischen Alphabeten enthalten.
  • Die Groß-/Kleinschreibung ist schwieriger als es scheint. Verschiedene geschriebene Sprachen haben nicht nur unterschiedliche Buchstaben, sondern auch unterschiedliche Groß-/Kleinschreibungen für einige gleiche Buchstaben.

Die andere sehreinfachWahl anstelle \wdessen, was mir einfällt - Namen zu erlauben, alles zu enthaltenandereals Leerzeichen oder ein ,--kann erreicht werden, indem jedes \wdurch ersetzt wird [^,\S]. Das [ ]macht einZeichenklasse, das führende ^Mittel, die Klasse enthält alleAberdie angegebenen Zeichen (das istnichtbezogen auf seine Bedeutung außerhalb einer Zeichenklasse), ,spezifiziert sich wörtlich und\sgibt alle Leerzeichen an.

perl -wpe 's/^([^,\s]+),\s*([^,\s]).*/$1\L$2/' file

Weitere Informationen zu regulären Ausdrücken in Perl finden Sie unterperldoc perlretutUndperldoc perlreDas Problem, das Sie dargestellt haben, istNurkomplex genug, um mich zu motivieren, ein anspruchsvolleres (und damit komplizierteres) Tool als die grundlegenden Textverarbeitungstools zu verwenden. Da Sie wahrscheinlich einen Weg finden, dies mit diesen Tools zu tun, kann ich es Ihnen sicherlich nicht verübeln, wenn Sie es tun! Aber ich denke, dies könnte für zukünftige, noch komplexere Probleme dennoch hilfreich sein.

Antwort2

Die vorgeschlagene Lösung mit Cut, Pipes, Tr, Paste (und Sed) könnte sein:

cut -f1 -d, foo >bar; cut -f2 -d" " foo | cut -c1 |tr "A-Z" "a-z" >bar2 ;paste bar bar2|sed -e "s/\x9//g"

wobei foo die Datei mit Ihrer Eingabe ist. Sie können die Aufgabe also mit cut und anderen erledigen, aber die Pearl-Lösung ist eleganter und angemessener.

verwandte Informationen