Объединять файлы, помещая между ними пустую строку

Скорее всего, это произошло из-за того, что вы использовали два разных менеджера пакетов(dpkgили его внешний интерфейс apt-getи сам pip)с одним и тем же префиксом(/usr). Я предполагаю, что либо

  • недавнее apt-get upgradeобновление некоторых зависимостей, но некоторые другие файлы, которые были установлены pip, не обновились, потому что dpkgи apt-getпросто не знали о них ИЛИ
  • вы удалили пакет с apt-get remove, и поскольку apt-getничего не знал об использовании этого пакета (, так как другой пакет был установлен pipи, следовательно, не в базе данных dpkg), он не предупредил вас о взломе других пакетов.

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

Не используйте несколько разных менеджеров пакетов.Всегда используйте только один менеджер пакетов для данного (поддерева -)вашей файловой системы, иначе вы получите несоответствия и/или конфликты. Менеджер пакетов Debian для дерева /usrназывается dpkg, и без его вызова никто не должен никогда касаться /usr.

Конечно, не помогает то, что большинство связанных с python -людей, с которыми вы столкнетесь, попытаются протолкнуть pip, даже говоря вам sudo pip install; не надо. По какой-то причине существуют дистрибутивы, содержащие материалы для Python. Также см. этот связанный вопрос на AskUbuntu и этот ответ на StackOverflow .


Вы можете попытаться устранить беспорядок, установив свежий пункт с помощью

apt-get purge python-pip python3-pip
apt-get install python-pip python3-pip

однако могут быть оставлены файлы, которые могут мешать работе, о которых dpkgне знает, поскольку они были установлены pip. Надежным -огневым способом будет проверка всех файлов в /usr/lib/python*на предмет их принадлежности к пакету debian, и если нет, то удаление их без исключения.

Опять же, только используют dpkgи его интерфейсные инструменты, такие как apt-get, aptitude, synaptic,... для модификации /usr. Если вам нужно установить что-либо общесистемное -, чего нет в виде пакета .deb, либо создайте пакет и установите его с dpkg, либо установите его с /usr/local.

7
11.01.2021, 14:29
7 ответов

Использование GNUsed:

sed -s -e $'$a\\\n'./*.txt >concat.out

Это объединяет все данные в concat.outи в то же время добавляет пустую строку в конец каждого обрабатываемого файла.

Опция -sдля GNU sedзаставляет адрес $соответствовать последней строке в каждого файла вместо, как обычно, последней строки всех данных. Команда aдобавляет одну или несколько строк в указанное место, а добавляемые данные являются новой строкой. Новая строка кодируется как $'\n', то есть как «строка C -», что означает, что мы используем оболочку, которая понимает эти (как bashилиzsh). В противном случае это должно было бы быть добавлено как буквальная новая строка:

sed -s -e '$a\
'./*.txt >concat.out

На самом деле, '$a\\'и '$a\ ', кажется, тоже работают, но я не совсем уверен, почему.

Это также работает, если кто-то считает, что команда aслишком утомительна, чтобы ее правильно выполнить:

sed -s -e '${p;g;}'./*.txt >concat.out

Любая из этих вариаций также будет вставлять пустую строку в конец вывода последнего файла. Если эта последняя новая строка не нужна, удалите ее, передав общий результат через sed '$d'перед перенаправлением в выходной файл :

.
sed -s -e '${p;g;}'./*.txt | sed -e '$d' >concat.out
9
18.03.2021, 22:37

Пример использования Perl.

$ perl -e 'while(<>){print}continue{print"\n" if eof}' *.txt > concat.txt

, который можно упростить до

$ perl -ne 'print; print "\n" if eof' [abc].txt > concat.txt
0
18.03.2021, 22:37

Не одна команда, а простой -лайнер:

for f in *.txt; do cat -- "$f"; printf "\n"; done > newfile.txt

Это выдаст эту ошибку:

cat: newfile.txt: input file is output file

Но вы можете игнорировать это, по крайней мере, в системах GNU/Linux. Стефан Шазеля указал в комментариях, что, по-видимому, в других системах это может привести к бесконечному циклу, поэтому, чтобы избежать этого,попробуй:

for f in *.txt; do 
    [[ "$f" = newfile.txt ]] || { cat -- "$f"; printf "\n"; }
done > newfile.txt

Или просто не добавляйте расширение .txtк выходному файлу (оно не нужно и вообще не имеет никакого значения )так что оно не будет включено в петля:

for f in *.txt; do cat -- "$f"; printf "\n"; done > newfile
9
18.03.2021, 22:37

Использование GNUawk:

gawk -v RS='^$' -v ORS= '{
    print sep $0; sep="\n";
}'./file*.txt >single.file

см. Режим Slurp -в awk?

префиксная точка -косая черта в имени файла ./используется, чтобы избежать проблем с файлами с именами, подобными file=x.txt, например, поскольку awkчитает такие строки как переменная , если они идут после кодов awk;

Другим подходом GNU awkможет быть:

gawk 'BEGINFILE{if (ARGIND>1) print ""};1'./file*.txt >single.txt

что лучше, поскольку добавляет пустую строку, даже если последняя строка не заканчивается символом новой строки, и позволяет избежать загрузки всех файлов в память.


существует также sedальтернатива, но чтобы удалить самую последнюю \newline, вы должны добавить еще одну вертикальную черту sed... | , чтобы удалить ее.

sed -s '$s/$/\n/' file*.txt >single.file
4
18.03.2021, 22:37

zshимеет квалификатор Pglob для префикса каждого имени файла, полученного из glob с произвольным аргументом.

Хотя он обычно используется для таких вещей, как cmd *.txt(P[-i])для префикса каждого имени файла с заданной опцией, вы можете использовать здесь, чтобы вставить любой файл перед каждым файлом. Временный файл, содержащий пустую строку, можно сделать с помощью =(print), поэтому вы можете сделать:

() { cat file*.txt(P[$1]); } =(print)

В Linux или Cygwin вы также можете:

cat file*.txt(P[/dev/stdin]) <<< ''
5
18.03.2021, 22:37

Возможно, это не совсем то, что вы искали, но, как предложил Квазимодо в комментарии, GNU tailможет добавить пустую строку в дополнение к заголовку с именем файла:

$ echo 'this is foo' > foo.txt 
$ echo 'this is bar' > bar.txt   
$ tail -n+1 foo.txt bar.txt 
==> foo.txt <==
this is foo

==> bar.txt <==
this is bar

-n+1заставляет печатать весь файл; это означает «печатать хвост, начиная с первой строки».

Если вы хотите, чтобы заголовок добавлялся даже при наличии только одного файла для согласованности, вы можете использовать -v.

$ tail -n+1 foo.txt        
this is foo
$ tail -v -n+1 foo.txt 
==> foo.txt <==
this is foo
4
18.03.2021, 22:37

Это не работает в POSIX /bin/sh, но вbash:

cat file1 <(echo) file2 >concatenated

<(echo)заменяется временным именованным каналом, который подключается к выходным данным команды echo, которая создает одну новую строку.

1
18.03.2021, 22:37

Теги

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