Jak usunąć wszystko po drugim dwukropku w drugiej kolumnie i zachować wszystko inne?

Nov 19 2020

Mam pilnik ( file.bim) z około 1,5 miliona. linie wyglądające następująco:

1   1:819959:C:T    0   819959  T   C
1   1:821249:G:A    0   821249  A   G
1   1:821477:A:G    0   821477  G   A
1   1:821843:C:T    0   821843  T   C
1   1:823963:A:C    0   823963  C   A
1   1:824357:C:T    0   824357  T   C
1   1:824398:A:C    0   824398  C   A
1   1:827972:G:A    0   827972  A   G
1   1:828539:A:T    0   828539  T   A

W drugiej kolumnie chciałbym usunąć drugi dwukropek i trzy następujące po nim znaki, a pozostałe kolumny pozostawić bez zmian. Żądane wyjście jest następujące ( updated_file.bim):

1   1:819959    0   819959  T   C
1   1:821249    0   821249  A   G
1   1:821477    0   821477  G   A
1   1:821843    0   821843  T   C
1   1:823963    0   823963  C   A
1   1:824357    0   824357  T   C
1   1:824398    0   824398  C   A
1   1:827972    0   827972  A   G
1   1:828539    0   828539  T   A

Próbowałem użyć awk, ale tutaj tylko dwukropki są usuwane, ale litery między nimi pozostają:

awk -F":" '{ print $1":"$2,$3,$4,$5,$6 }' file.bim > updated_file.bim

Odpowiedzi

2 AdminBee Nov 19 2020 at 18:20

Możesz użyć następującego awkprogramu:

awk '{sub(/:[^:]*:[^:]*$/,"",$2)}1' file.bim > updated_file.bim

lub

awk '{sub(/(:[^:]*){2}$/,"",$2)}1' file.bim > updated_file.bim

Spowoduje to użycie sub()funkcji do edycji drugiej kolumny ( $2) poprzez zastąpienie dwóch ostatnich :i następującego po nich tekstu „nic”, co skutecznie usunie tę część.

Jeśli plik wyjściowy powinien być rozdzielany tabulatorami, użyj awk -v OFS="\t" ' ... '.

Alternatywnie , jeśli plik jest rozdzielany grupami zawierającymi więcej niż jedną „spację” i chcesz mieć pewność, że formatowanie separatora jest całkowicie niezmienione, możesz użyć

awk '{sub(/:[^:]*:[^: ]* /," ")}1' file.bim > updated_file.bim

który będzie szukać wzorca " :, po którym następuje tekst, po którym :następuje tekst, po którym następuje spacja" i zastępuje ten wzorzec pojedynczą "spacją". W danych wejściowych ten wzorzec występuje tylko na końcu kolumny 2, więc zastąpienie będzie miało wpływ tylko na tę kolumnę.

Wreszcie , jeśli kiedykolwiek w przyszłości liczba :oddzielonych pól w drugiej kolumnie może się zmienić, ale nadal chcesz zachować tylko pierwsze dwa, możesz skorzystać z mojego oryginalnego, choć mniej przenośnego wariantu, który zastępuje drugą kolumnę przez tylko tekst wokół pierwszego :(zamiast tekstu za dwoma ostatnimi z „nic”):

awk '{$2=gensub(/([^:]+:[^:]+).*/,"\\1","1",$2)}1' file.bim > updated_file.bim
2 αғsнιη Nov 19 2020 at 18:45

Usuń wszystko po drugim dwukropku w drugiej kolumnie i zachowaj wszystko inne:

awk '{ c=split($2, s, ":"); $2=s[1] (c>1?":":"") s[2]; }1' infile

jak zauważyłeś, usuwa to powtarzające się spacje, gdy ponownie oceniamy drugą kolumnę, jeśli nie jest to duży problem po twojej stronie; w przeciwnym razie użyj poniżej sedjako alternatywy:

sed -E 's/^([^ ]* *)([^: ]*:[^: ]*):[^ ]* (.*)/\1\2 \3/' infile

Data testu;

::1   1:81995:9:C:T    0   8::199:59  T   C
1:a:  :1821249GA:    0   821:2:4  A   G
111   1:828539::    0   :::828539  T   A

wynik:

::1   1:81995    0   8::199:59  T   C
1:a:  :1821249GA    0   821:2:4  A   G
111   1:828539    0   :::828539  T   A
1 EdMorton Nov 20 2020 at 06:59

Z GNU sed dla \S:

$ sed 's/\(:[^:]*\)\S*/\1/' file
1   1:819959    0   819959  T   C
1   1:821249    0   821249  A   G
1   1:821477    0   821477  G   A
1   1:821843    0   821843  T   C
1   1:823963    0   823963  C   A
1   1:824357    0   824357  T   C
1   1:824398    0   824398  C   A
1   1:827972    0   827972  A   G
1   1:828539    0   828539  T   A

lub z dowolnym sedem POSIX:

$ sed 's/\(:[^:]*\)[^[:space:]]*/\1/' file
1   1:819959    0   819959  T   C
1   1:821249    0   821249  A   G
1   1:821477    0   821477  G   A
1   1:821843    0   821843  T   C
1   1:823963    0   823963  C   A
1   1:824357    0   824357  T   C
1   1:824398    0   824398  C   A
1   1:827972    0   827972  A   G
1   1:828539    0   828539  T   A
RedaSalih Nov 19 2020 at 18:07

Użyj seda, aby zamienić wszystkie puste spacje na ":", a następnie odrzuć pola 6 $ i 7 $ i umieść zawartość 4 $ i 5 $ na $ 5 za pomocą awk:

sed  's/ /:/g' bim | awk  -F':' '{ $6=""; $7="" ; $4=$4$5; $5="" }1' > updated_file.bim 

BEZ SED:

awk  '{ gsub(/ /,":",$0); FS=":";$6=""; $7="" ; $4=$4$5; $5="" }1' bim > updated_file.bim 
CarlosPascual Nov 19 2020 at 19:05

z awkpierwszym razem substr($2, 1, 8)wybierasz od 2 $, czego potrzebujesz. I wypisz wartość szamiast $2. Więc twój kod z tym może być:

awk 's = substr($2, 1, 8) {print $1, s, $3, $4, $5, $6}' file
1 1:819959 0 819959 T C
1 1:821249 0 821249 A G
1 1:821477 0 821477 G A
1 1:821843 0 821843 T C
1 1:823963 0 823963 C A
1 1:824357 0 824357 T C
1 1:824398 0 824398 C A
1 1:827972 0 827972 A G
1 1:828539 0 828539 T A

Zaktualizowano, aby zachować spacje:

awk -F '[[:blank:]]{2,}' '$2 = substr($2, 1, 8) {print $1, $2, $3, $4, $5, $6}' file | column -t
1  1:819959  0  819959  T  C
1  1:821249  0  821249  A  G
1  1:821477  0  821477  G  A
1  1:821843  0  821843  T  C
1  1:823963  0  823963  C  A
1  1:824357  0  824357  T  C
1  1:824398  0  824398  C  A
1  1:827972  0  827972  A  G
1  1:828539  0  828539  T  A
codeholic24 Nov 19 2020 at 19:16

Następujące dane wyjściowe można uzyskać za pomocą sedpolecenia

cat file.bim | sed 's/:[a-zA-Z]//g' >> updated_file.bim

or

cat file.bim | sed 's/:[[:alpha:]]//g' >> updated_file.bim

Wynik :

1   1:819959    0   819959  T   C
1   1:821249    0   821249  A   G
1   1:821477    0   821477  G   A
1   1:821843    0   821843  T   C
1   1:823963    0   823963  C   A
1   1:824357    0   824357  T   C
1   1:824398    0   824398  C   A
1   1:827972    0   827972  A   G
1   1:828539    0   828539  T   A