
Ich habe eine Datei wie diese
ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402.5
ILMN_1343295 CTTCAACAGCGACACCCACTCCTCCACCTTTGACGCTGGGGCTGGCATTG NM_002046.3
ILMN_1651209 TCACGGCGTACGCCCTCATGGGGAAAATCTCCCCGGTGACTTTCAGGTCC NM_182838.1
Ich möchte die numerischen Erweiterungen am Ende der 3. Spalte entfernen, damit meine Ausgabedatei so aussieht
ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402
ILMN_1343295 CTTCAACAGCGACACCCACTCCTCCACCTTTGACGCTGGGGCTGGCATTG NM_002046
ILMN_1651209 TCACGGCGTACGCCCTCATGGGGAAAATCTCCCCGGTGACTTTCAGGTCC NM_182838
Wie kann ich dies in der Befehlszeile tun, vorzugsweise mit awk
? Ich kann dies in tun, perl
aber ich bin ziemlich sicher, dass es dafür eine einzige Befehlszeile gibt.
Antwort1
Mit awk:
awk -F'.' '{print $1}' file
-F
Option: Standard-Feldtrennzeichen (Leerzeichen) in Punkt (.) ändern.
$1
ist der Index der Feldposition (mit . Feldtrennzeichen).
{ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402}.{5}
^^ field index is $1 ^^$2
Mit rev und awk:
rev file | awk -F'.' '{print $2}'|rev # reverse characters of each lines,\
print field number 2 with (.) separator \
and reverse the result again
Das rev
Dienstprogramm kopiert die angegebenen Dateien in die Standardausgabe und kehrt dabei die Reihenfolge der Zeichen in jeder Zeile um. Wenn keine Dateien angegeben sind, wird die Standardeingabe gelesen.
Mit sed:
sed 's/.[0-9]*$//' file
sed 's/.[^.]*$//' file
$
Zeigen Sie auf das Zeilenende. Suchen Sie im ersten sed-Befehl nach Zeichen (.), auf das null oder mehr Zahlen folgen, und ersetzen Sie diese durch Leerzeichen.
Entfernen Sie im zweiten sed-Befehl alles, worauf ein (.) folgt, und entfernen Sie auch den Punkt (.) selbst.
Mit rev und sed:
rev file| sed 's/.*[.]//' |rev
Löschen Sie alles vor dem Punkt (.). Schließen Sie auch . selbst ein und entfernen Sie es.
Mit grep:
grep -oP '.*(?=\.[0-9])' file
-o, --only-matching Drucken Sie nur die übereinstimmenden (nicht leeren) Teile einer übereinstimmenden Zeile. wobei sich jeder dieser Teile auf einer separaten Ausgabeleitung befindet. -P, --perl-regexp Interpretieren Sie PATTERN als Perl-kompatiblen regulären Ausdruck (PCRE).
(?=pattern)
: Positiver Lookahead: Die positive Lookahead-Konstruktion besteht aus einem Paar Klammern, wobei auf die öffnende Klammer ein Fragezeichen und ein Gleichheitszeichen folgen.
.*(?=\.[0-9])
: (positiver Vorausblick) passt zu allem( .*
), gefolgt von einem Punkt(.) und allen Vorkommen von Zahlen, ohne das Muster( \.[0-9]
) in die Übereinstimmung einzubeziehen.
Mit rev und grep:
rev file |grep -oP '(?<=[0-9]\.).*' |rev
rev file |grep -oP '[0-9]\.\K.*' |rev
(?<=pattern)
: Positiver Lookbehind. Ein Paar Klammern, wobei auf die öffnende Klammer ein Fragezeichen, ein „Kleiner-als“-Symbol und ein Gleichheitszeichen folgen.
(?<=[0-9]\.).*
(positiver Lookbehind) passt zu allem, worauf beliebige Zahlen folgen und was mit einem Punkt (.) endet.
Im zweiten Grep-Befehl können Sie Nifty \K
anstelle der Lookbehind-Assertion verwenden.
Mit Schnitt:
cut -f1 -d. file
cut -c 1-77 file # Print first 77 characters of each line.
Ausschneiden - Abschnitte aus jeder Dateizeile entfernen -d, --delimiter=DELIM Verwenden Sie DELIM statt TAB als Feldtrennzeichen -f, --fields=LISTE Wählen Sie nur diese Felder aus; -c, --characters=LISTE Wählen Sie nur diese Zeichen aus
Mit while-Schleife:
while read line; do echo "${line::-2}";done <file
Dies funktioniert, wenn Sie am Ende jeder Zeile nur Zahlen mit der Länge 1 haben und diese eine feste Länge haben. Der obige Befehl entfernt die letzten beiden Zeichen am Ende jeder Zeile in der Eingabedatei. Alternative Befehle sind ${line%??}
:
Antwort2
Angenommen, die Erweiterungen sind ausschließlich Ziffern:
perl -pi -e 's/\.\d+$//' /path/to/file
-i
führt die Bearbeitung direkt durch (wie in sed
). \d
bedeutet Ziffern und $
kennzeichnet das Zeilenende.
Mit awk
:
awk 'gsub(/\.[0-9]+$/,"")' /path/to/file
gawk
hat in neueren Versionen eine Option zur direkten Bearbeitung, aber ich bin nicht sicher, wie portabel diese ist. gsub
unterstützt einen optionalen Parameter, der die Zielspalte angibt:
awk 'gsub(/\.[0-9]+$/,"",$3)' /path/to/file
Die letzte Form hat den unerwünschten Nebeneffekt, dass in der Ausgabe jede Spalte durch ein einzelnes Leerzeichen getrennt wird, als ob Sie Folgendes getan hätten print $1,..,$NF
. Ich weiß nicht, warum.
Antwort3
Die Verwendung awk
ist unkompliziert. Legen Sie Ihren Feldtrenner einfach wie folgt fest .
:
awk -F. '{print $1}' file
Ein anderer Ansatz unter Verwendung der Shell (in diesem Fall Bash):
while IFS=.; read -r lines _; do line+=("$lines"); done <file
printf "%s\n" "${line[@]}"
ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402
ILMN_1343295 CTTCAACAGCGACACCCACTCCTCCACCTTTGACGCTGGGGCTGGCATTG NM_002046
ILMN_1651209 TCACGGCGTACGCCCTCATGGGGAAAATCTCCCCGGTGACTTTCAGGTCC NM_182838
Antwort4
Dadurch wird alles entfernt, was mit dem Punkt beginnt:
sed 's/\..*//'