Как объединить несколько строк вывода в одну строку?


157

Если я запускаю команду cat file | grep pattern, я получаю много строк вывода. Как объединить все строки в одну строку, эффективно заменив каждую "\n"из них на "\" "(конец заканчивается "пробелом)?

cat file | grep pattern | xargs sed s/\n/ /g не работает для меня


Кстати: (1) вам нужно поместить ваш sedскрипт в одинарные кавычки, чтобы Bash не связывался с ним (так как sed s/\n/ /gвызывает sedс двумя аргументами, а именно s/n/и /g); (2) , так как вы хотите выход cat file | grep patternбыть вход в sed, а не аргументы в sed, необходимо устранить xargs; и (3) здесь нет необходимости cat, поскольку он grepможет принимать имя файла в качестве второго аргумента. Итак, вы должны были попробовать grep pattern file | sed 's/\n/ /g'. (В этом случае это не сработало бы по причинам, указанным в приведенной выше ссылке, но теперь вы знаете, на будущее.)
ruakh


Вопрос с 68 голосами (140k просмотров) дублируется с постом, который имеет только 1 голос (12k просмотров)? Это не правильно.
Кенорб

Ответы:


230

Используйте tr '\n' ' 'для перевода всех символов новой строки в пробелы:

$ grep pattern file | tr '\n' ' '

Примечание: grepчитает файлы, catобъединяет файлы. Не надо cat file | grep!

Редактировать:

trможет обрабатывать только односимвольные переводы. Вы можете использовать awkдля изменения разделителя выходной записи, например:

$ grep pattern file | awk '{print}' ORS='" '

Это преобразовало бы:

one
two 
three

чтобы:

one" two" three" 

3
При таком подходе вы в конце получаете нежелательное пространство.
Сорин

1
Вам нужно добавить echo ""в конце, чтобы добавить новую строку перед текстом приглашения.
nexayq

1
Это хорошо работает, однако я не хочу, чтобы разделитель отображался в самой последней записи. Например, по вашему ", это выглядит как one" two" three", однако я хотел бы, чтобы это отображалось как one" two" three. Обратите внимание, что последние три не имеют круглых скобок. Любые идеи?
хрю

2
@oink, вы можете передать результаты, sed '$s/..$//'чтобы удалить последние 2 символа в последней строке.
Крис Сеймур

3
Если вы хотите заменить символы новой строки ни на что, вам нужно использовать эту --deleteопцию, так как по умолчанию ожидается два аргумента. например tr --delete '\n'.
Элайджа Линн

69

Конвейер вывода до xargsобъединит каждую строку вывода в одну строку с пробелами:

grep pattern file | xargs

Или любая команда, например. ls | xargs, Предел xargsвывода по умолчанию составляет ~ 4096 символов, но его можно увеличить, например, с помощью. xargs -s 8192,


| tr '\n' ' 'не работал для меня, когда вызывается через php execфункцию. Он игнорировал tr и просто давал последний матч от grep. | xargsработал.
Адарша

3
Это решение также имеет то преимущество, что оно «съедает» пробелы из входных данных. +1
Рене

55

В bash echoбез кавычек удаляйте возврат каретки, табуляцию и несколько пробелов

echo $(cat file)

8
Ответ здесь сильно недооценен, это действительно просто и работает как талисман, с завершающим переводом строки.
Dangercrow

Это особенно аккуратно, если вы используетеIFS="$(printf '\n\t')"
aggsol

5
Или просто echo $(<file)... использование эха не только аккуратнее, чем использование tr '\n' ' ', но и лучше (подумайте об \r\nокончании строки). @aggsol, ты можешь просто сказатьIFS=$'\n\t'
Normadize

Как насчет без места?
ДимиДак

22

Это может быть то, что вы хотите

cat file | grep pattern | paste -sd' '

Что касается вашего редактирования, я не уверен, что это значит, возможно, это?

cat file | grep pattern | paste -sd'~' | sed -e 's/~/" "/g'

(это предполагает, что ~не происходит в file)


2
@ Стефану не нужно было предполагать, что это cat fileбудет на самом деле catили даже файл. (Я просто оставил эту часть без изменений, поскольку это не имело отношения к вопросу)
сехе

5

Это пример, который производит вывод через запятую. Вы можете заменить запятую на любой разделитель, который вам нужен.

cat <<EOD | xargs | sed 's/ /,/g'
> 1
> 2
> 3
> 4
> 5
> EOD

производит:

1,2,3,4,5

3

Вот метод с использованием exредактора (часть Vim ):

  • J ойн всех линий и р RINT в стандартный выходной поток:

    $ ex +%j +%p -scq! file
  • J ойн все линии в месте (в файле):

    $ ex +%j -scwq file

    Примечание: это объединит все строки внутри самого файла!


2

Самые быстрые и простые способы, которые я знаю, чтобы решить эту проблему:

Когда мы хотим заменить символ новой строки \n пробелом :

xargs < file

xargsимеет собственные ограничения на количество символов в строке и количество всех символов в сочетании, но мы можем увеличить их. Подробности можно узнать, выполнив эту команду: xargs --show-limitsи, конечно, в руководстве:man xargs

Когда мы хотим заменить один символ другим точно таким же :

tr '\n' ' ' < file

Когда мы хотим заменить один символ на множество символов :

tr '\n' '~' < file | sed s/~/many_characters/g

Сначала мы заменяем символы новой строки \nдля тильд ~(или выбираем другой уникальный символ, отсутствующий в тексте), а затем заменяем символы тильды любыми другими символами ( many_characters) и делаем это для каждой тильды (флага g).


0

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

$ awk ' /pattern/ {print}' ORS=' ' /path/to/file

Он объединит все строки в одну с пробелом


Вам не нужно, {print}так как это действие по умолчанию в awk.
Суровая

0

Вот еще один простой метод с использованием awk:

# cat > file.txt
a
b
c

# cat file.txt | awk '{ printf("%s ", $0) }'
a b c

Кроме того, если в вашем файле есть столбцы, это упрощает объединение только определенных столбцов:

# cat > cols.txt
a b c
d e f

# cat cols.txt | awk '{ printf("%s ", $2) }'
b e

-1

На Red Hat Linux я просто использую echo:

echo $ (cat / some / file / name)

Это дает мне все записи файла в одну строку.


2
Это уже был ответ в 2015 году. Вы просто дублируете этот ответ . Пожалуйста, прочитайте ответы, прежде чем публиковать свои собственные, особенно когда на вопрос 7 лет и уже есть 8 ответов.
Микаэль Б.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.