63

I have a file containing a certain number of lines. Each line looks like this:

TF_list_to_test10004/Nus_k0.345_t0.1_e0.1.adj:PKMYT1

I would like to remove all before ":" character in order to retain only PKMYT1 that is a gene name. Since I'm not an expert in regex scripting can anyone help me to do this using Unix (sed or awk) or in R?

Wiktor Stribiżew
  • 561,645
  • 34
  • 376
  • 476
Elb
  • 2,127
  • 4
  • 26
  • 36

10 Answers10

98

Here are two ways of doing it in R:

foo <- "TF_list_to_test10004/Nus_k0.345_t0.1_e0.1.adj:PKMYT1"

# Remove all before and up to ":":
gsub(".*:","",foo)

# Extract everything behind ":":
regmatches(foo,gregexpr("(?<=:).*",foo,perl=TRUE))
Sacha Epskamp
  • 44,659
  • 18
  • 110
  • 130
  • 19
    Also, if any of the gene names might themselves self contain a `:`, you could match and replace up to the *first* `:` using `gsub("^[^:]*:", "", foo)` – Josh O'Brien Sep 06 '12 at 15:49
20

A simple regular expression used with gsub():

x <- "TF_list_to_test10004/Nus_k0.345_t0.1_e0.1.adj:PKMYT1"
gsub(".*:", "", x)
"PKMYT1"

See ?regex or ?gsub for more help.

Andrie
  • 170,733
  • 42
  • 434
  • 486
10

Using sed:

sed 's/.*://' < your_input_file > output_file

This will replace anything followed by a colon with nothing, so it'll remove everything up to and including the last colon on each line (because * is greedy by default).

As per Josh O'Brien's comment, if you wanted to only replace up to and including the first colon, do this:

sed "s/[^:]*://"

That will match anything that isn't a colon, followed by one colon, and replace with nothing.

Note that for both of these patterns they'll stop on the first match on each line. If you want to make a replace happen for every match on a line, add the 'g' (global) option to the end of the command.

Also note that on linux (but not on OSX) you can edit a file in-place with -i eg:

sed -i 's/.*://' your_file
John Carter
  • 52,342
  • 26
  • 107
  • 142
10

There are certainly more than 2 ways in R. Here's another.

unlist(lapply(strsplit(foo, ':', fixed = TRUE), '[', 2))

If the string has a constant length I imagine substr would be faster than this or regex methods.

John
  • 22,773
  • 6
  • 54
  • 82
6

You can use awk like this:

awk -F: '{print $2}' /your/file
Costi Ciudatu
  • 35,138
  • 6
  • 55
  • 91
5

Solution using str_remove from the stringr package:

str_remove("TF_list_to_test10004/Nus_k0.345_t0.1_e0.1.adj:PKMYT1", ".*:")
[1] "PKMYT1"
ToWii
  • 451
  • 5
  • 7
3

Some very simple move that I missed from the best response @Sacha Epskamp was to use the sub function, in this case to take everything before the ":"(instead of removing it), so it was very simple:

foo <- "TF_list_to_test10004/Nus_k0.345_t0.1_e0.1.adj:PKMYT1"

# 1st, as she did to remove all before and up to ":":
gsub(".*:","",foo)

# 2nd, to keep everything before and up to ":": 
gsub(":.*","",foo)

Basically, the same thing, just change the ":" position inside the sub argument. Hope it will help.

2

If you have GNU coreutils available use cut:

cut -d: -f2 infile
Thor
  • 42,211
  • 10
  • 116
  • 125
2

I was working on a similar issue. John's and Josh O'Brien's advice did the trick. I started with this tibble:

library(dplyr)
my_tibble <- tibble(Col1=c("ABC:Content","BCDE:MoreContent","FG:Conent:with:colons"))

It looks like:

  | Col1 
1 | ABC:Content 
2 | BCDE:MoreContent 
3 | FG:Content:with:colons

I needed to create this tibble:

  | Col1                  | Col2 | Col3 
1 | ABC:Content           | ABC  | Content 
2 | BCDE:MoreContent      | BCDE | MoreContent 
3 | FG:Content:with:colons| FG   | Content:with:colons

And did so with this code (R version 3.4.2).

my_tibble2 <- mutate(my_tibble
        ,Col2 = unlist(lapply(strsplit(Col1, ':',fixed = TRUE), '[', 1))
        ,Col3 = gsub("^[^:]*:", "", Col1))
Leslie Sage
  • 376
  • 2
  • 8
0

Below are 2 equivalent solutions:

The first uses perl's -a autosplit feature to split each line into fields using :, populate the F fields array, and print the 2nd field $F[1] (counted starting from field 0)

perl -F: -lane 'print $F[1]' file

The second uses a regular expression to substitute s/// from ^ the beginning of the line, .*: any characters ending with a colon, with nothing

perl -pe 's/^.*://' file
Chris Koknat
  • 3,082
  • 2
  • 28
  • 29