Как извлечь символ (<<) и соответствующие ему алфавиты из строки с помощью sed, awk или grep

Ковариационная модель ДНК один/один файл: входные данные

Заголовок: последовательность и ковариация

NC_013791.2.2 : GCTCAGCTGGCtAGAG
NC_013791.2.2 : >>>>.........<<<
NC_013791.2.3 : GCTCAGCTGGCtAGAG
NC_013791.2.3 : >>>>..<<<<......
NC_013791.2.4 : GCTCAGCTGGCtAGGA
NC_013791.2.4 : >>>>.........<<<
NC_013791.2.5 : GCTCAGCTGACtACAG
NC_013791.2.5 : >>>>..<<<<......

выходные данные/ожидаемые данные для всех вышеуказанных идентификаторов из одного/одного файла

NC_013791.2.2 :  GAG
NC_013791.2.2 :  <<<
NC_013791.2.3 : CTGG
NC_013791.2.3 : <<<<
NC_013791.2.4 : GGA
NC_013791.2.4 : <<<
NC_013791.2.5 : CTGA
NC_013791.2.5 : <<<<
  1. Я могу удалить последний символ с помощью: sed 's/.$//', как предложено в stackflow.

  2. извлеките последние символы с помощью: rev sym.txt | cut -c 1-3 | rev

  3. извлечь только < с помощью grep: grep -Eo "<.{3}" sym.txt

но я не могу извлечь, как показано ниже

GAG
<<<
GAGC
<<<<

или ГАГК <<<<

Может ли кто-нибудь помочь с sed, awk или grep - заранее спасибо

@Morton: Могу ли я узнать, почему я не могу проголосовать за обоих (@Stuffy и @Potong), поскольку их вклад будет полезен для будущих изменений людям, которые работают в биологии. Спасибо.

Pandu C 26.04.2024 13:35

Насколько я знаю, вы можете голосовать за кого угодно. Что бы ни заставило вас думать, что вы не можете голосовать за любое количество людей, которые вам нравятся, извините, но я не тот человек, которого можно об этом спрашивать, я всего лишь участник сайта, как и вы. Может быть, отметить вопрос или ответ, чтобы задать его модератору?

Ed Morton 26.04.2024 18:15
В чем разница между методом "==" и equals()
В чем разница между методом "==" и equals()
Это один из наиболее часто задаваемых вопросов новичкам на собеседовании. Давайте обсудим его на примере.
Замена символа по определенному индексу в JavaScript
Замена символа по определенному индексу в JavaScript
В JavaScript существует несколько способов заменить символ в строке по определенному индексу.
1
2
131
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

если я правильно понимаю, вы хотите напечатать все символы < плюс символы над символами <

Я попробовал это

$ awk '{
        if (match($0, /<+/)) {
                print $1, $2, substr(prevline, RSTART, RLENGTH)
                print $1, $2, substr($0, RSTART, RLENGTH)
                next
        }
}

{
        prevline = $0
}' file

NC_013791.2.2 : GAG
NC_013791.2.2 : <<<
NC_013791.2.3 : CTGG
NC_013791.2.3 : <<<<
NC_013791.2.4 : GGA
NC_013791.2.4 : <<<
NC_013791.2.5 : CTGA
NC_013791.2.5 : <<<<

Большое спасибо, это работает, не могли бы вы дать какое-нибудь объяснение, где я могу пройти (так как я новичок). Я попробовал «команду AWK», которую вы предоставили с заголовком и последовательностью + ковариацией (как показано ниже, через табуляцию), но она стерла все символы, кроме необходимых. NC_013791.2.trna2 GCTCAGCTGGCtAGAG NC_013791.2.trna2 >>>>.........<<< ожидается NC_013791.2.trna2 GAG NC_013791.2.trna2 <<< не могли бы вы помочь, как изменить команда-заранее спасибо

Pandu C 26.04.2024 10:43

Я не понимаю, как ввод из 8 строк переходит в вывод из 4 строк.

stuffy 27.04.2024 00:54

@stuffy-извините, что запутал, c отредактируйте, введите 8 строк, чтобы вывести 8 строк. Не могли бы вы внести/изменить свой код для вывода (т. е. включая заголовки) в соответствии с просьбой и как показано/изменено Потонгом. Спасибо вам обоим.

Pandu C 27.04.2024 12:26

Я добавил заголовки и формат с помощью -o-

stuffy 29.04.2024 02:12

Это может сработать для вас (GNU sed):

sed -E 'N;:a;s/^.(.*\n)[^<]|.(\n.*)[^<]$/\1\2/;ta;' file

Используйте расширенное регулярное выражение, установив опцию -E.

Добавьте следующую строку.

Ввести цикл.

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


После дальнейших разъяснений(?), возможно:

cat <<\! > file
NC_013791.2.2 : GCTCAGCTGGCtAGAG
NC_013791.2.2 : >>>>.........<<<
!

cat <<\! > file1
NC_013791.2.3 : GCTCAGCTGGCtAGAG
NC_013791.2.3 : >>>>..<<<<......
!

cat <<\! > file2
NC_013791.2.2 : GCTCAGCTGGCtAGAG
NC_013791.2.2 : >>>>.........<<<
NC_013791.2.3 : GCTCAGCTGGCtAGAG
NC_013791.2.3 : >>>>..<<<<......
NC_013791.2.4 : GCTCAGCTGGCtAGAG
NC_013791.2.4 : >>>>.........<<<
NC_013791.2.5 : GCTCAGCTGGCtAGAG
NC_013791.2.5 : >>>>..<<<<......
!

sed -E 'N;:a;s/^(.*: ).(.*\n\1)[^<]|.(\n.*)[^<]$/\1\2\3/;ta' file file1
NC_013791.2.2 : GAG
NC_013791.2.2 : <<<
NC_013791.2.3 : CTGG
NC_013791.2.3 : <<<<

sed -E 'N;:a;s/^(.*: ).(.*\n\1)[^<]|.(\n.*)[^<]$/\1\2\3/;ta' file2
NC_013791.2.2 : GAG
NC_013791.2.2 : <<<
NC_013791.2.3 : CTGG
NC_013791.2.3 : <<<<
NC_013791.2.4 : GAG
NC_013791.2.4 : <<<
NC_013791.2.5 : CTGG
NC_013791.2.5 : <<<<

Большое спасибо. Я попробовал вашу команду, но она работает по-другому (если в файле 10 пар) - она ​​работает с 1, 3 и т. д.

Pandu C 26.04.2024 10:45

@PanduC Возможно, вы могли бы показать точные входные данные и точную форму выходных данных (не в формате jpg, а в виде открытого текста).

potong 26.04.2024 11:12

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

Pandu C 26.04.2024 11:44

@ Potong: спасибо, это работает, когда есть два отдельных файла (файл + файл1), как указано, но я не могу работать с «одним файлом» (у меня ~ 46 тысяч идентификаторов в одном файле). Не могли бы вы сообщить мне, как изменить работу с одним файлом, и объяснить, что означает N,a,\1,\2\3,ta ?

Pandu C 26.04.2024 13:30

@PanduC как выглядит один файл?

potong 26.04.2024 17:51

@Potong, я показал, как выглядит отдельный файл, см. изменения выше.

Pandu C 26.04.2024 23:16

Спасибо всем участникам за предоставление ценных кодов.

Pandu C 03.05.2024 10:51
Ответ принят как подходящий

Если ваши данные всегда в этом формате, вы можете распечатать первые два поля, а затем вызвать substr, который напечатает интересующую часть.

Основываясь на ответе @stuffy, вы можете изменить код, чтобы он соответствовал 3 или более раз символу <:

awk 'match($0, /<<<+/) { 
  print $1, $2, substr(prev, RSTART, RLENGTH)
  print $1, $2, substr($0, RSTART, RLENGTH)
} { 
  prev = $0
}' file

Здесь $0 — текущая строка, а prev — предыдущая строка.

Функция match устанавливает предопределенные переменные RSTART и RLENGTH, которые вы можете использовать для вызова substr.

Выход

NC_013791.2.2 : GAG
NC_013791.2.2 : <<<
NC_013791.2.3 : CTGG
NC_013791.2.3 : <<<<
NC_013791.2.4 : GGA
NC_013791.2.4 : <<<
NC_013791.2.5 : CTGA
NC_013791.2.5 : <<<<

Если, например, разделителем полей является : , и вы хотите проверить, что обе части перед этим одинаковы в обеих строках:

awk -F" : " '
  match($2, /<<<+/) && key == $1 {
    print $1 FS substr(val, RSTART, RLENGTH)
    print $1 FS substr($2, RSTART, RLENGTH)
  }
  { val = $2; key = $1 }
' file

Используя любой awk плюс tac:

$ cat tst.awk
match($3,/<+/) {
    start = RSTART
    lgth = RLENGTH
}
{
    $3 = substr($3,start,lgth)
    print
}

$ tac file | awk -f tst.awk | tac
NC_013791.2.2 : GAG
NC_013791.2.2 : <<<
NC_013791.2.3 : CTGG
NC_013791.2.3 : <<<<
NC_013791.2.4 : GGA
NC_013791.2.4 : <<<
NC_013791.2.5 : CTGA
NC_013791.2.5 : <<<<

Другие вопросы по теме