Як об'єднати кілька ліній виводу в один рядок?


158

Якщо я запускаю команду 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 переглядів)? Це неправильно.
kenorb

Відповіді:


231

Використовуйте 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
При такому підході ви закінчуєте небажаний простір наприкінці.
sorin

1
Вам потрібно додати echo ""в кінці, щоб додати новий рядок перед текстом підказки.
nexayq

1
Це чудово виходить, однак я не хочу, щоб розділювач з’являвся в останній запис. Приклад, на ваш ", він відображається як one" two" three", але я хотів би, щоб він відображався як one" two" three. Зверніть увагу, що в останніх трьох немає дужок. Будь-які ідеї?
oink

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

3
Якщо ви хочете замінити нові рядки нічим, вам потрібно скористатися --deleteопцією, оскільки за замовчуванням очікується два аргументи. напр tr --delete '\n'.
Ілля Лінн

69

Piping output для 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)... використання echo - це не просто акуратніше, ніж використання tr '\n' ' ', але й краще (думки \r\nзакінчення). @aggsol ви можете просто сказатиIFS=$'\n\t'
Normadize

А як без місця?
DimiDak

22

Це може бути те, що ви хочете

cat file | grep pattern | paste -sd' '

Щодо вашої редакції, я не впевнений, що це означає, можливо, це?

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

(це передбачає, що ~не відбувається в file)


2
@Stephan не було потреби припускати, що cat fileнасправді це буде cat, або навіть файл. (Я просто залишив цю частину без змін, оскільки це не стосується питання)
15:15

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 oin всі рядки на місці (у файлі):

    $ ex +%j -scwq file

    Примітка. Це об'єднає всі рядки у файлі it-self!


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

У червоному капелюсі Linux я просто використовую ехо:

echo $ (cat / some / файл / ім'я)

Це дає мені всі записи файлу лише в одному рядку.


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