Как объединить несколько строк с именами файлов в одну с пользовательским разделителем? - PullRequest
375 голосов
/ 04 мая 2010

Я хотел бы объединить результат ls -1 в одну строку и разделить его тем, что я хочу.

Существуют ли какие-либо стандартные команды Linux, которые я могу использовать для достижения этой цели?

Ответы [ 20 ]

4 голосов
/ 28 декабря 2016

Похоже, ответы уже существуют.

Если хочешь a, b, c формат, используйте ls -m ( ответ Тулаинса Кордовы )

Или, если вы хотите a b c формат, используйте ls | xargs (упрощенная версия Chris J's answer )

Или, если вам нужен какой-либо другой разделитель, например |, используйте ls | paste -sd'|' (применение Ответ Артема )

3 голосов
/ 04 мая 2010

Если ваша версия xargs поддерживает флаг -d, тогда это должно работать

ls  | xargs -d, -L 1 echo

-d - флаг-разделитель

Если у вас нет -d, вы можете попробовать следующее

ls | xargs -I {} echo {}, | xargs echo

Первый xargs позволяет вам указать разделитель, который в этом примере является запятой.

3 голосов
/ 20 августа 2014
sed -e :a -e '/$/N; s/\n/\\n/; ta' [filename]

Пояснение:

-e - обозначает команду для выполнения
:a - это этикетка
/$/N - определяет область совпадения для текущей и (N) ext строки
s/\n/\\n/; - заменяет все EOL на \n
ta; - перейти к метке a, если совпадение прошло успешно

Взято из моего блога .

3 голосов
/ 28 января 2018

Седь,

sed -e ':a; N; $!ba; s/\n/,/g'
  # :a         # label called 'a'
  # N          # append next line into Pattern Space (see info sed)
  # $!ba       # if it's the last line ($) do not (!) jump to (b) label :a (a) - break loop
  # s/\n/,/g   # any substitution you want

Примечание

Это линейная сложность, которая заменяется только один раз после добавления всех строк в шаблонное пространство sed.

@ AnandRajaseka's answer и некоторые другие подобные ответы, такие как here , являются O (n²), потому что sed должен выполнять замену каждый раз, когда новая строка добавляется Пространство образца.

Для сравнения

seq 1 100000 | sed ':a; N; $!ba; s/\n/,/g' | head -c 80
  # linear, in less than 0.1s
seq 1 100000 | sed ':a; /$/N; s/\n/,/; ta' | head -c 80
  # quadratic, hung
2 голосов
/ 04 мая 2010

Вы можете использовать:

ls -1 | perl -pe 's/\n$/some_delimiter/'
2 голосов
/ 13 сентября 2012

ls создает один выходной столбец при подключении к трубе, поэтому -1 является избыточным.

Вот еще один ответ Perl с использованием встроенной функции join, которая не оставляет завершающий разделитель:

ls | perl -F'\n' -0777 -anE 'say join ",", @F'

Непонятный -0777 заставляет perl прочитать все вводные данные перед запуском программы.

альтернатива sed, не оставляющая конечного разделителя

ls | sed '$!s/$/,/' | tr -d '\n'
1 голос
/ 03 апреля 2017

Добавляем поверх ответа majkinetor, вот способ удаления конечного разделителя (так как я пока не могу просто комментировать под его ответом):

ls -1 | awk 'ORS=","' | head -c -1

Просто удалите столько конечных байтов, сколько рассчитывает ваш разделитель.

Мне нравится этот подход, потому что я могу использовать многосимвольные разделители + другие преимущества awk:

ls -1 | awk 'ORS=", "' | head -c -2

EDIT

Как заметил Питер, отрицательный счетчик байтов не поддерживается в родной версии головы MacOS. Однако это легко исправить.

Сначала установите coreutils. «Основные утилиты GNU - это основные утилиты для работы с файлами, оболочками и текстом в операционной системе GNU».

brew install coreutils

Команды, также предоставляемые MacOS, устанавливаются с префиксом «g». Например gls.

Как только вы это сделаете, вы можете использовать ghead с отрицательным числом байтов или лучше, сделать псевдоним:

alias head="ghead"
0 голосов
/ 12 июня 2019

Quick Perl версия с конечной обработкой косой черты:

ls -1 | perl -E 'say join ", ", map {chomp; $_} <>'

Объяснить:

  • perl -E: запустить Perl с поддержкой функций (скажем, ...)
  • скажем: печать с возвратом носителя
  • join ",", ARRAY_HERE: присоединить массив с помощью ","
  • map {chomp; $ _} ROWS: убрать из каждой строки оператор возврата и вернуть результат
  • <>: stdin, каждая строка является строкой, в сочетании с картой она создаст массив каждой строки
0 голосов
/ 27 апреля 2016

Вы можете использовать chomp для объединения нескольких строк в одну строку:

perl -e 'while (<>) {if (/ \ $ /) {chomp; } print;} 'bad0> test

ставить условие разрыва строки в операторе if. Это может быть специальный символ или любой разделитель.

0 голосов
/ 30 апреля 2013

ls имеет опцию -m для разделения вывода с ", " запятой и пробелом.

ls -m | tr -d ' ' | tr ',' ';'

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

в моем примере я заменяю разделитель , на разделитель ;

замените ; любым одним символом-разделителем , который вы предпочитаете, поскольку tr учитывает только первый символ в строках, которые вы передаете в качестве аргументов.

...