Linux команда объединить файл к себе n раз

13979
Bryce Thomas

Я взял книгу в формате простого текстового файла от Project Gutenberg (около 0,5 МБ), которую я хочу объединить с самим собой n, чтобы сгенерировать большой текстовый файл, с которым я могу сравнить некоторые алгоритмы. Есть ли команда Linux, которую я могу использовать для достижения этой цели? catЗвучит идеально, но, кажется, не слишком хорошо работает с конкатенацией файла на себя, плюс не затрагивает nвременную часть вопроса.

28
использовать какую-то петлю и добавлять? так повторите foo.txt >> bar.txt и заверните это во что-то, что будет запускать команду много раз? Journeyman Geek 12 лет назад 2

3 ответа на вопрос

31
Journeyman Geek

Для меня это две части - во-первых - использовать cat для вывода текстового файла в стандартный вывод и использовать append для добавления его в другой файл - например, foo.txt >> bar.txt добавит foo.txt к bar.txt

затем запустить его n раз с

for i in ;do cat foo.txt >> bar.txt; done 

заменив в этой команде свой номер

должно работать, где n ваш номер

Если вы используете csh, есть команда «repeat».

повторяющиеся связанные части ответа скопированы отсюда, и я проверил его в системе Ubuntu 11.04 в оболочке bash по умолчанию.

Интересный факт: на самом деле это работает без замены 'n', в этом случае он будет выполнять тело один раз для каждого символа между ASCII '1' и ASCII 'n' (так 62 раза). Но `` будет правильно запускать тело 12 раз. Arnout Engelen 8 лет назад 2
Возможно, вы захотите просто перенаправить весь конвейер, а не добавлять в каждую итерацию: `for i в ; do cat foo.txt; done> bar.txt` Toby Speight 7 лет назад 1
1
phicr

Мне скучно, так что вот еще несколько способов, как объединить файл с самим собой, в основном с headпомощью костыля. Простите, если я переобъясню себя, я просто люблю говорить: P


Предполагается, Nчто это число самоконкатенаций, которые вы хотите сделать, и имя вашего файла file.

Переменные:

linecount=$(<file wc -l)  total_repeats=$(echo "2^$N - 1" | bc) # obtained through the power of MATH  total_lines=$((linecount*(total_repeats+1)))  tmp=$(mktemp --suffix .concat.self) 

Учитывая копия fileназывается file2, total_repeatsэто число раз fileнужно будет добавить к file2сделать то же самое, как если бы fileбыл сцеплены для себя Nраз.

Сказал, что МАТ здесь, более или менее: МАТ (сущность)

Это первый семестр по информатике, но прошло много времени с тех пор, как я сделал доказательство индукции, поэтому я не могу с этим справиться ... (также хорошо известен этот класс рекурсии, 2^Loopsтак что это тоже есть ...)


POSIX

Я использую несколько не-posix вещей, но они не являются необходимыми. Для моих целей:

 yes() { while true; do echo "$1"; done; } 

О, я только использовал это. Ну что ж, раздел уже здесь ...


методы


head с отслеживанием linecount.

ln=$linecount for i in $(seq 1 $N); do <file head -n $ln >> file; ln=$((ln*2)) done 

Нет временных файлов, нет кота, даже не слишком много математики, все радость.


teeс математикой

<file tee -a file | head -n $total_lines > $tmp cat $tmp > file 

Здесь teeпроисходит чтение, fileно постоянное добавление к нему, поэтому он будет продолжать чтение файла при повторении, пока не headостановит его. И мы знаем, когда остановить это из-за МАТ . Добавление идет за борт, поэтому я использовал временный файл. Вы также можете обрезать лишние строки file.


evalПовелитель тьмы!

eval "cat $(yes file | head -n $((total_repeats+1)) | tr '\n' ' ')" > $tmp cat $tmp > file 

Это просто расширяется cat file file file ...и исчезает. Вы можете сделать это и без $tmpфайла:

eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" | head -n $((total_lines-linecount)) >> file 

Вторая head«хитрость» cat- поместить посредника между операцией записи. Вы могли бы обмануть catи другого, catно это противоречиво. Попробуй это:

test_double_cat() { local Expected=0 local Got=0 local R=0 local file="$(mktemp --suffix .double.cat)" for i in $(seq 1 100); do  printf "" > $file echo "1" >> $file echo "2" >> $file echo "3" >> $file  Expected=$((3*$(<file wc -l)))  cat $file $file | cat >> $file  Got=$(<file wc -l)  [ "$Expected" = "$Got" ] && R="$((R+1))" done echo "Got it right $R/100" rm $file } 

sed:

<file tr '\n' '\0' | sed -e "s/.*/$(yes '\0' | head -n $total_repeats | tr -d '\n')/g" | tr '\0' '\n' >> file 

Вынуждает sedчитать весь файл как строку, захватывает все это, затем вставляет это $total_repeatsчисло раз.

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

find_missing_char() { local file="$"  firstbyte="$(<$file fold -w1 | od -An -tuC | sort -un | head -n 1)" if [ ! "$firstbyte" = "0" ]; then echo "\0" else printf "\\$(printf '%03o\t' $((firstbyte-1)) )" fi } 

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

rm $tmp

1
Toby Speight

Вы, конечно, можете использовать catдля этого:

$ cat /tmp/f foo $ cat /tmp/foo /tmp/f foo foo 

Для того, чтобы получить $nкопии, вы можете использовать yesВодопроводный в head -n $n:

$ yes /tmp/f | head -n 10 /tmp/f /tmp/f /tmp/f /tmp/f /tmp/f /tmp/f /tmp/f /tmp/f /tmp/f /tmp/f 

Соедини это дает

yes /tmp/f | head -n $n | xargs cat >/tmp/output 

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