Я новичок в bash и мне нужна помощь, чтобы скопировать строку 2 и далее из одного файла в определенную позицию (150 символов) в другом файле. Просматривая форум, я нашел способ включить конкретный текст, указанный в этой позиции:
sed -i 's / ^ (. {150}) / \ 1specifictextlisted /' destinationfile.txt
Однако я не могу найти способ скопировать в это содержимое из одного файла.
По сути, я работаю с этими двумя стартовыми файлами, и мне нужен следующий результат:
Содержание файла 1:
Sequence
AAAAAAAAAGGGGGGGGGGGCCCCCCCCCTTTTTTTTT
Содержание файла 2:
chr2
tccccagcccagccccggccccatccccagcccagcctatccccagcccagcctatccccagcccagccccggccccagccccagccccggccccagccccagccccggccccagccccggccccatccccggccccggccccatccccggccccggccccggccccggccccggccccatccccagcccagccccagccccatccccagcccagccccggcccagccccagcccagccccagccacagcccagccccggccccagccccggcccaggcccagcccca
Желаемое выходное содержимое:
chr2 tccccagcccagccccggccccatccccagcccagcctatccccagcccagcctatccccagcccagccccggccccagccccagccccggccccagccccagccccggccccagccccggccccatccccggccccggccccatccccgAAAAAAAAAGGGGGGGGGGGCCCCCCCCCTTTTTTTTTgccccggccccggccccggccccggccccatccccagcccagccccagccccatccccagcccagccccggcccagccccagcccagccccagccacagcccagccccggccccagccccggcccaggcccagcccca
Может ли кто-нибудь направить меня на правильный путь к достижению этого?
Для этого можно использовать awk
:
awk 'NR==FNR{a=$2;next}{print $1, substr($2, 0, 149) "" a "" substr($2, 150)}' file1 file2
Объяснение:
# Total row number == row number in file
# This is only true when processing file1
NR==FNR {
a=$2 # store column 2 in a variable 'a'
next # do not process the block below
}
# Because of the 'next' statement above, this
# block gets only executed for file2
{
# put 'a' in the middle of the second column and print it
print $1, substr($2, 0, 149) "" a "" substr($2, 150)
}
Я предполагаю, что оба файла содержат только одну строку, как в вашем примере.
Обновлено: в комментариях вы сказали, что файлы на самом деле занимают две строки, в этом случае вы можете использовать следующий скрипт awk:
# usage: awk -f this_file.awk file1 file2
# True for the second line in each file
FNR==2 {
# Total line number equals line number in file
# This is only true while we are processing file1
if (NR==FNR) {
insert=$0 # Store the string to be inserted in a variable
} else {
# Insert the string in file1
# Assigning to $0 will modify the current line
$0 = substr($0, 0, 149) "" insert "" substr($0, 150)
}
}
# Print lines of file2 (line 2 has been modified above)
NR!=FNR
Предполагая, что у вас есть только одна строка после заголовка последовательности, просто добавьте условие вроде !/^>/
перед открывающей фигурной скобкой в последнем блоке и добавьте /^>/
после закрывающей фигурной скобки, чтобы пройти и распечатать заголовок последовательности.
Доброе утро! :) Извините, я спал. Я исправлю это, когда приду на работу
Вы можете использовать bash и читать по одному символу за раз из файла:
i=1
while read -n 1 -r; do
echo -n "$REPLY"
let i++
if [ $i -eq 150 ]; then
echo -n "AAAAAAAAAGGGGGGGGGGGCCCCCCCCCTTTTTTTTT"
fi
done < chr2 > destinationfile.txt
Это просто считывает символ, отображает его и увеличивает счетчик. Если счетчик равен 150, он повторяет вашу последовательность. Вы можете заменить эхо на cat file | tr -d '\n'
. Просто убедитесь, что удалили все символы новой строки, как здесь, с tr
. Вот почему я использую echo -n
, поэтому он ничего не добавляет.
Спасибо за ответ. Я частично успешно протестировал ваш код здесь: i=1; while read -n 1 -r; do echo -n $REPLY; let i++; if [ $i -eq 150 ]; then echo -n "AAAAAAAAAGGGGGGGGGGGCCCCCCCCCTTTTTTTTT"; fi;done < file2 > file1
Можно ли добиться этого без включения последовательности «AAAAAAAAAGGGGGGGGGGGCCCCCCCCCTTTTTTTTT»? В нынешнем виде я могу добиться того же с sed -i 's/^(.{150})/\1AAAAAAAAAGGGGGGGGGGGCCCCCCCCCTTTTTTTTT/' file2
, но суть в том, чтобы взять его из строки 2 отдельного файла и не указывать в коде, поскольку я буду использовать это со многими файлами с разными последовательностями.
вы можете удалить новую строку, добавив после нее | tr -d '\n'
. Мой другой ответ тоже должен работать.
Если файл действительно огромен, а не всего 327 символов, вы можете использовать dd:
dd if=chr2 bs=1 count=150 status=none of=destinationfile.txt
tr -d '\n' < Sequence >> destinationfile.txt
dd if=chr2 bs=1 skip=150 seek=189 status=none of=destinationfile.txt
189 - это 150 + длина Sequence
.
Должен ли последний параметр быть of=destinationfile.txt
или вы хотите иметь два разных файла вывода?
@tripleee да, конечно, спасибо, что заметили это, и этот кот стал ненужным.
tr
не может прочитать аргумент файла, вам нужно использовать перенаправление ввода. Но да, cat
на одном файле всегда бесполезен.
Спасибо за этот пример. Прошу прощения, но форматирование файла, который я скопировал и вставил, изначально показывал содержимое файла 1 как одну строку, но на самом деле это две строки (отредактированные в основном сообщении). Аналогично, файл 2 содержит начальную строку с «Chr2» перед строкой последовательности ниже. Я ввел приведенный выше код с моими именами файлов вместо file1 и file2, но результат остается неизменным. Следует ли мне изменять что-либо еще в вашем коде, чтобы он работал правильно?