Как заменить пробелы после определенного шаблона запятыми? - PullRequest
0 голосов
/ 24 января 2019

Я новичок в кодировании и пытаюсь отформатировать некоторые данные биоинформатики. Я пытаюсь удалить все пробелы после GT:GL:GOF:GQ:NR:NV запятыми, но не все, что не в формате xx:xx:xx:xx:xx (как в примере). Я знаю, что мне нужно использовать sed с параметром регулярных выражений, но я не очень хорошо знаю, как его использовать. Я никогда раньше не использовал sed и запутался, пытаясь оценить любую помощь. Извините, если я плохо отформатировал (это мой первый пост).

РЕДАКТИРОВАТЬ 2: На этот раз я получил фактические данные из файла, которые могут помочь решить проблему. Убрал плохой пример.

Новый пример: я извлек эти данные из моего фактического файла (это всего лишь два образца), и он окружен другими данными. По существу, строка содержит набор данных, за которыми следует «GT: GL: GOF: GQ: NR: NV», после этого появляется больше данных в формате, показанном ниже, и, наконец, есть еще несколько случайных данных. К сожалению, я не могу опубликовать полную строку данных, потому что она очень длинная и не подходит.

Input

0/1:-1,-1,-1:146:28:14,14:4,0 0/1:-1,-1,-1:134:6:2,2:1,0

выход

0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2:1,0

Ответы [ 5 ]

0 голосов
/ 26 января 2019

perl myscript.pl '0/1: -1, -1, -1: 146: 28: 14,14: 4,0 0/1: -1, -1, -1: 134: 6: 2 , 2: 1,0'

myscript.pl

  #!/usr/local/ActivePerl-5.20/bin/env perl
    my $input = $ARGV[0];
    $input =~ s/ /\,/g; 
    print $input, "\n";
__DATA__

выход

0/1: -1, -1, -1: 146: 28: 14,14: 4,0,0 / 1: -1, -1, -1: 134: 6: 2,2: 1 , 0

Это удалит все пробелы, а не только рассматриваемое пространство

0 голосов
/ 24 января 2019

Не могли бы вы попробовать следующее.Это позаботится о печати тех значений, которые НЕ соответствуют совпадению с регулярным выражением.Также мы бы сделали регулярное выражение, упомянутое в match, немного короче, сделав его [0-9]+\.{4} и т. Д., Поскольку это проверено на старом awk, поэтому не может его протестировать.

awk '
BEGIN{
  OFS=","
}
match($0,/GT:GL:GOF:GQ:NR:NV [0-9]+:[0-9]+:[0-9]+:[0-9]+:[0-9]+/){
  value=substr($0,RSTART!=1?1:RSTART,RSTART+RLENGTH-1)
  value1=substr($0,RSTART+RLENGTH+1)
  gsub(/[[:space:]]+/,",",value1)
  print value,value1
  next
}
1
'  Input_file
0 голосов
/ 24 января 2019

Вы также можете достичь желаемого результата без регулярных выражений, используя awk:

awk '{printf "%s", $1FS$2FS$3FS$4FS$5","$6","$7; for (i=8;i<=NF;i++) printf "%s", FS$i; print ""}' input.txt

По сути, он выводит из поля 1–5 с разделителем полей по умолчанию («пробел»), затем из поля 5 в7 с разделителем-запятой, затем с поля 8 и далее с разделителем по умолчанию.

0 голосов
/ 24 января 2019

С помощью базовых регулярных выражений вы можете использовать классы символов и обратные ссылки для выполнения своей задачи, например,

$ sed 's/\([0-9][0-9]*:[0-9][0-9]*\)[ ]\([0-9][0-9]*:[0-9][0-9]*\)/\1,\2/g' file
1/0 ./. 0/1 GT:GL:GOF:GQ:NR:NV 1:12:314,213:132:13:31,14:31:31 AB GT BB
1/0 ./. 0/1 GT:GL:GOF:GQ:NR:NV 10:13:12,41:41:1:13,13:131:1:1 AB GT RT
1/0 ./. 0/1 GT:GL:GOF:GQ:NR:NV 1:12:314,213:132:13:31,14:31:31 AB GT

Что в основном говорит:

  • найти и перехватить любую [0-9][0-9]* одну или несколько цифр,
  • разделены : и
  • , за которым следует [0-9][0-9]* одна или несколько цифр - в качестве группы захвата 1,
  • соответствует пробелу после группы захвата 1, за которой следует группа захвата 2 (которая совпадает с группой захвата 1),
  • затем замените пространство, разделяющее группы захвата, на запятую, заново вставив текст группы захвата, используя обратные ссылки 1 и 2 (например, \1 и \2), наконец
  • сделать замену global (например, g), чтобы заменить все совпадающие вхождения.

Редактирование на основе нового введенного сообщения

Если вам все еще нужно добавить все оригинальные запятые, и , то теперь вы хотите добавить запятую между ,0 0/ (где перед запятой стоит цифра, за которой следует заменить пробел с запятой, за которой следует однозначная цифра и косая черта), тогда все, что вам нужно сделать, - это сделать свои группы захвата условными (либо захват исходных данных, как указано выше, либо захват нового сегмента. включая ИЛИ (например, \| в основных терминах регулярных выражений) между условиями.

Например, добавив \|,[0-9] в конце первой группы захвата и \|[0-9][/] в конце второй, например,

$ sed 's/\([0-9][0-9]*:[0-9][0-9]*\|,[0-9]\)[ ]\([0-9][0-9]*:[0-9][0-9]*\|[0-9][/]\)/\1,\2/g' file
0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2:1,0

Если у вас есть другие предупреждения в вашем файле, я предлагаю вам опубликовать несколько полных строк ввода, а если они слишком длинные, то создайте файл zip, gzip, bzip или xz и разместите его на сайте, таком как pastebin, и добавьте ссылка на ваш вопрос.

Если сейчас все, что вас действительно волнует, это пробел в ,0 0/, то вы можете сократить команду sed до:

$ sed 's/\(,[0-9]\)[[:space:]]\([0-9][/]\)/\1,\2/g' file
0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2:1,0

( note: Я включил [[:space:]] для обработки любых пробелов (пробел, табуляция, ...) вместо просто литерала [ ] (пробел) в новом примере) Дайте мне знать, если это решит проблему.

0 голосов
/ 24 января 2019

Я предполагаю, что xx:xx:xx или xx:xx:xx:xx могут иметь любое количество деталей, так как у некоторых есть 3, а у некоторых 4.

Это довольно сложно сделать надежно с sed, так как он не поддерживает обходные пути, которые кажутся необходимыми для этого примера.

Вы можете попробовать что-то вроде:

perl -pe 's/(?<=\d) (?=\d+(:\d+){2,})/,/g' input.txt

Если ваше сердце настроено на sed, вы можете попробовать это, но в некоторых случаях оно может пропустить:

sed -r 's/(:[0-9]+) ([0-9]+:)/\1,\2/g' input.txt
...