Вставьте содержимое файла в другое (в отдельной строке отправляемого файла) - BASH/LINUX

Я попытался сделать это с помощью cat, а затем после ввода второго файла я добавил | head -$line | tail -1, но он не работает, потому что он сначала выполняет cat.

Любые идеи? Мне нужно сделать это с помощью cat или что-то еще.

Ответ 1

Я бы использовал sed для этого задания:

line=3
sed -e "${line}r file2" file1

Если вы хотите перезаписать file1 и у вас есть GNU sed, добавьте параметр -i. В противном случае, напишите во временный файл, а затем скопируйте/переместите временный файл поверх оригинала, очистите его по необходимости (это тег trap ниже). Примечание: копирование временного файла сохраняет ссылки; перемещение не (но более быстрое, особенно если файл большой).

line=3
tmp="./sed.$$"
trap "rm -f $tmp; exit 1" 0 1 2 3 13 15
sed -e "${line}r file2" file1 > $tmp
cp $tmp file1
rm -f $tmp
trap 0

Ответ 2

Просто для удовольствия, и только потому, что мы все любим ed, стандартный редактор, здесь ed. Он очень эффективен (ed является подлинным текстовым редактором)!

ed -s file2 <<< $'3r file1\nw'

Если номер строки сохраняется в переменной line, то:

ed -s file2 <<< "${line}r file1"$'\nw'

Просто, чтобы угодить Заку, здесь одна версия с меньшим багизмом, если вам не нравится bash (лично мне не нравятся трубы и подоболочки, я предпочитаю herestrings, но эй, как я сказал, что только угодить Заку):

printf "%s\n" "${line}r file1" w | ed -s file2

или (чтобы угодить Сорпигалу):

printf "%dr %s\nw" "$line" file1 | ed -s file2

Как упоминает Джонатан Леффлер в комментарии, и если вы намереваетесь использовать этот метод в script, используйте heredoc (он обычно самый эффективный):

ed -s file2 <<EOF
${line}r file1
w
EOF

Надеюсь, это поможет!

P.S. Не стесняйтесь оставлять комментарий, если вы чувствуете, что вам нужно выразить себя о том, как управлять стандартным редактором ed.

Ответ 3

cat file1 >>file2

добавит содержимое файла1 в файл2.

cat file1 file2

будет конкатенация файлов1 и file2 и отправки вывода на терминал.

cat file1 file2 >file3

создаст или переит файл3 с конкатенацией файлов file1 и file2

cat file1 file2 >>file3

добавит конкатенацию file1 и file2 в конец файла3.

Edit

Для транкинга файла2 перед добавлением файла1:

sed -e '11,$d' -i file2 && cat file1 >>file2

или для создания файла с 500 строками:

n=$((500-$(wc -l <file1)))
sed -e "1,${n}d" -i file2 && cat file1 >>file2

Ответ 4

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

Сначала установите тестовую среду

rm -rf /tmp/test
mkdir /tmp/test
printf '%s\n' {0..9} > /tmp/test/f1
printf '%s\n' {one,two,three,four,five,six,seven,eight,nine,ten} > /tmp/test/f2

Теперь давайте сделаем инструмент, и в этом первом проходе мы будем плохо его реализовывать.

# insert contents of file $1 into file $2 at line $3
insert_at () { insert="$1" ; into="$2" ; at="$3" ; { head -n $at "$into" ; ((at++)) ; cat "$insert" ; tail -n +$at "$into" ; } ; }

Затем запустите инструмент, чтобы увидеть удивительные результаты.

$ insert_at /tmp/test/f1 /tmp/test/f2 5

Но подождите, результат на stdout! Как насчет перезаписи оригинала? Нет проблем, мы можем сделать еще один инструмент для этого.

insert_at_replace () { tmp=$(mktemp) ; insert_at "[email protected]" > "$tmp" ; mv "$tmp" "$2" ; }

И запустите его

$ insert_at_replace /tmp/test/f1 /tmp/test/f2 5
$ cat /tmp/test/f2

"Ваша реализация отстой!"

Я знаю, но это красота создания простых инструментов. Позвольте заменить insert_at на версию sed.

insert_at () { insert="$1" ; into="$2" ; at="$3" ; sed -e "${at}r ${insert}" "$into" ; }

И insert_at_replace продолжает работать (конечно). Реализация insert_at_replace также может быть изменена, чтобы быть менее глючной, но я оставлю это как упражнение для читателя.

Ответ 5

Мне нравится делать это с head и tail если вы не возражаете управлять новым файлом:

head -n 16 file1 >  file3 &&
cat        file2 >> file3 &&
tail -n+56 file1 >> file3

Вы можете свернуть это в одну строку, если хотите. Затем, если вам действительно нужно перезаписать файл file1, выполните: mv file3 file1 (опционально && между командами).

Заметки:

  • head -n 16 file1 означает первые 16 строк file1
  • tail -n+56 file1 означает file1, начиная со строки 56 и заканчивая
  • Следовательно, я фактически пропустил строки с 17 по 55 из файла file1.
  • Конечно, если вы можете изменить 56 на 17, то ни одна строка не будет пропущена.
  • Я предпочитаю смешивать простые команды " head и " tail а затем попробовать магическую команду " sed.