Как я могу скопировать строки из нескольких файлов в один файл и назвать строки как исходное имя файла

тл;др

$ date +'%s%3N'
1506298414529

баш

Строгое решение bash (без внешних исполняемых файлов )невозможно, начиная с bash 4.2:

$ printf '%(%s)T\n' "-1"
1506298414

$ printf '%(%Y%m%d-%H:%M:%S)T\n' "-1"
20170924-20:13:34

Но это не позволяет ни миллисекунды, ни наносекунды (пока ).

дата

Чтобы получить миллисекунды или наносекунды, вам нужно использовать дату GNU, как это:

$ printf '%s\n' "$(date +'%Y%m%d-%H:%M:%S.%N')"
20170924-20:13:34.326113922

Или

$ printf '%s\n' "$(date +'%s.%N')"
1506298414.529678016

Ограничение до 3 цифр в дробной части секунд может быть получено с помощью формата %.3fдля printf:

$ printf '%.3f\n' "$(date +'%s.%N')"
1506298414.529

Или, что лучше, используйте возможность уменьшить количество цифр, которое допускает формат даты в наносекундах:

$ printf '%s\n' "$(date +'%s.%3N')"
1506298414.529

И тогда точку можно убрать:

$ printf '%s\n' "$(date +'%s%3N')"
1506298414529

Конечно, в данном случае более подходящим кажется более простое решение (без printf вместо того, что было задано ):

$ date +'%s%3N'
1506298414529
0
10.01.2020, 11:27
5 ответов

Учитывая опубликованный вами пример ввода/вывода и принятый вами ответ, все, что вам действительно нужно, это использовать GNU awk для ARGIND:

awk -F'>' -v OFS='\t' 'NF>1{print $2, "Bin_"ARGIND}' /Usr/Bin/bin*.fa > /User/Bin/Summary.txt

или с любым awk:

awk -F'>' -v OFS='\t' 'FNR==1{++c} NF>1{print $2, "Bin_"c}' /Usr/Bin/bin*.fa > /User/Bin/Summary.txt
0
28.01.2020, 02:57

Это должно быть возможно с GNU Awk:

awk 'match($0,/^>([^[:space:]]+)/,v) {match(FILENAME,/^.*bin\.([[:digit:]]+)\.fa$/,fid); printf("%s\tBin_%s\n", v[1], fid[1]+1);}' /User/Bin/bin.*.fa > summary.txt

Это будет:

  • сопоставить все строки, начинающиеся с >, и извлечь шаблон за символом >(до первого пробела )в переменную массива awkvс помощью функции match()в реализации GNU awk
  • сделайте то же самое, чтобы извлечь номер имени файла из текущего обрабатываемого имени файла (, хранящегося во внутренней переменной FILENAME), в переменную массиваfid
  • напечатать идентификатор contig (первый элементv)и идентификатор файла (Bin_, за которым следует увеличенное значениеfid[1])

Вывод вызова awkзатем перенаправляется в файлsummary.txt

Редактировать

Как предложил Эд Мортон, эффективность может быть повышена за счет извлечения идентификатора только при «изменении входного файла», что может быть обнаруженоFNR(по -номеру строки файла ), равному 1 (. ] при этом избегая возможных проблем, связанных с пробелами в нумерации имен файлов ).

Кроме того, использования match()можно избежать, обрезав строку, содержащую «идентификатор контига», от начального >и любого завершающего пробела; это также делает код более переносимым между awkреализациями.

awk 'FNR==1{n=split(FILENAME,fid,"[/.]"); out=fid[n-1]+1} index($0,">")==1{gsub(/(^>|[ \t]*$)/,""); printf("%s\tBin_%s\n", $0, out);}' /User/Bin/bin.*.fa
0
28.01.2020, 02:57
#!/usr/bin/env python

import os

files = os.listdir('/User/Bin')
for file in files:
    fi = open(file, 'r')
    n = file.split('.')[1]
    for line in fi:
        line = line.strip()
        if line.startswith('>'):
            bins = 'Bin_' + n
            print("%s\t%s" % (line[1:], bins))
    fi.close()

Пока вы используете Linux, у вас может быть установлен Python. Это может помочь.

0
28.01.2020, 02:57

Команда, которая может выполнить это, выглядит следующим образом:

grep "^>" /User/Bin/*.fa | awk -F ":>|\\." '{sub(".*/", "", $1);printf "%s\t%s_%d\n",$4,$1,$2+1}'

Позвольте мне объяснить различные шаги

grep "^>" /User/Bin/*.fa

Приведенная выше команда ищет только строки с требуемым шаблоном и печатает имена файлов вместе со строкой. Мы могли бы использовать только awk для вывода совпадающих строк, но с помощью grep мы упрощаем выполнение требуемых операций с именем файла.

awk -F ":>|\\." 

Это делает символы " :>" или "." в качестве разделителя полей, тем самым разделяя вывод grep на 4 части -1. имя файла до первого "." 2. имя индекса 3. Расширение 4. Выявлен фактический шаблон

{sub(".*/", "", $1)

Вышеупомянутый шаг удаляет базовое имя из имени файла в первой части.

printf "%s\t%s.%d\n",$4,$1,$2+1}

выполняет окончательную печать, где вторая часть увеличивается на 1, как вам нужно, и вставляется табуляция для разделения табуляции.

0
28.01.2020, 02:57

Попробуйте также

awk 'FNR == 1 {split (FILENAME, T, "."); FN = T[1] "_" ++T[2]}; /^>/ {print substr ($1, 2), FN}' *.fa
c_000000000001 bin_1
c_000000000002 bin_1
c_000000000003 bin_1
c_000000000004 bin_2
c_000000000005 bin_2
c_000000000006 bin_2
c_000000020120 bin_201
c_000000020121 bin_201
c_000000050122 bin_201
0
28.01.2020, 02:57

Теги

Похожие вопросы