
У меня есть такой файл
ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402.5
ILMN_1343295 CTTCAACAGCGACACCCACTCCTCCACCTTTGACGCTGGGGCTGGCATTG NM_002046.3
ILMN_1651209 TCACGGCGTACGCCCTCATGGGGAAAATCTCCCCGGTGACTTTCAGGTCC NM_182838.1
Я хочу удалить числовые расширения из конца третьего столбца, чтобы мой выходной файл выглядел следующим образом:
ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402
ILMN_1343295 CTTCAACAGCGACACCCACTCCTCCACCTTTGACGCTGGGGCTGGCATTG NM_002046
ILMN_1651209 TCACGGCGTACGCCCTCATGGGGAAAATCTCCCCGGTGACTTTCAGGTCC NM_182838
Как я могу сделать это в командной строке, желательно с помощью awk
? Я могу сделать это в , perl
но я почти уверен, что есть одна командная строка, чтобы сделать это.
решение1
С awk:
awk -F'.' '{print $1}' file
-F
опция изменения разделителя полей по умолчанию (пробел) на точку (.).
$1
- это индекс позиции поля (с разделителем полей .).
{ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402}.{5}
^^ field index is $1 ^^$2
С rev и awk:
rev file | awk -F'.' '{print $2}'|rev # reverse characters of each lines,\
print field number 2 with (.) separator \
and reverse the result again
Утилита rev
копирует указанные файлы в стандартный вывод, меняя порядок символов в каждой строке на обратный. Если файлы не указаны, считывается стандартный ввод.
С sed:
sed 's/.[0-9]*$//' file
sed 's/.[^.]*$//' file
$
указать на конец строки. В первой команде sed найдите символ (.), за которым следует ноль или более вхождений цифр, и замените их пробелами.
Во второй команде sed удалите все, что следует за (.), а также удалите саму точку (.).
С rev и sed:
rev file| sed 's/.*[.]//' |rev
Удалите все перед точкой (.). Также включите и удалите саму точку .
С помощью grep:
grep -oP '.*(?=\.[0-9])' file
-o, --only-matching Вывести только совпадающие (непустые) части совпадающей строки, с каждой такой частью на отдельной выходной линии. -P, --perl-regexp Интерпретировать PATTERN как регулярное выражение, совместимое с Perl (PCRE)
(?=pattern)
: Положительный просмотр вперед: конструкция положительного просмотра вперед представляет собой пару скобок, где за открывающейся скобкой следует вопросительный знак и знак равенства.
.*(?=\.[0-9])
: (положительный просмотр вперед) соответствует всему( .*
), за которым следует одна точка(.), и любым вхождениям цифр, не делая шаблон( \.[0-9]
) частью совпадения.
С rev и grep:
rev file |grep -oP '(?<=[0-9]\.).*' |rev
rev file |grep -oP '[0-9]\.\K.*' |rev
(?<=pattern)
: Положительный ретроспективный анализ. Пара скобок, за открывающей скобкой следует вопросительный знак, символ «меньше» и знак равенства.
(?<=[0-9]\.).*
(положительный просмотр назад) соответствует всему, за чем следуют любые вхождения цифр и которое заканчивается точкой (.).
Во второй команде grep вы можете использовать nifty \K
вместо утверждения lookbehind.
С разрезом:
cut -f1 -d. file
cut -c 1-77 file # Print first 77 characters of each line.
вырезать - удалить разделы из каждой строки файлов -d, --delimiter=РАЗДЕЛИТЕЛЬ используйте DELIM вместо TAB для разделителя полей -f, --fields=СПИСОК выберите только эти поля; -c, --characters=СПИСОК выберите только эти символы
С циклом while:
while read line; do echo "${line::-2}";done <file
Это сработает, если в конце каждой строки есть только числа с длиной = 1, и они имеют фиксированную длину. Приведенная выше команда удаляет последние два символа в конце каждой строки во входном файле. Альтернативные команды: ${line%??}
.
решение2
Предположим, что все расширения состоят из цифр:
perl -pi -e 's/\.\d+$//' /path/to/file
-i
выполняет редактирование на месте (как в sed
). \d
означает цифры и $
обозначает конец строки.
С awk
:
awk 'gsub(/\.[0-9]+$/,"")' /path/to/file
gawk
в новых версиях есть возможность редактирования на месте, но я не уверен, насколько она переносима. gsub
поддерживает необязательный параметр, указывающий целевой столбец:
awk 'gsub(/\.[0-9]+$/,"",$3)' /path/to/file
Последняя форма имеет нежелательный побочный эффект, заключающийся в разделении каждого столбца одним пробелом в выводе, как если бы вы сделали print $1,..,$NF
. Я не знаю, почему.
решение3
Использовать awk
его просто, просто установите разделитель полей следующим образом .
:
awk -F. '{print $1}' file
Другой подход с использованием оболочки (в данном случае 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
решение4
Это удалит все, что начинается с точки:
sed 's/\..*//'