Формат виводу xargs


10

Я хотів би змінити формат вихідних дисплеїв xargs

cat k.txt 
1 
2 
3 

І

cat k.txt | xargs 
1 2 3

Однак я хотів би мати 1, 2, 3або 1|2|3. Будь-які пропозиції?


Цього можна досягти за допомогою чогось (не зовсім цього) xargs cat -n, але простіше, якщо просто обрізати символи нового рядка, цього можна досягти echo $(cat), grepабо awk(проскакуйте спосіб це зробити). xargsне відповідають вашим поточним цілям.
41754

Відповіді:


18

Нижче наведено десяток прикладів того, як ви можете взяти такий файл, як цей:

$ cat k.txt
1
2
3

і конвертувати його у такий формат:

1,2,3

Ви можете використовувати цю команду для створення вищевказаного файлу, якщо ви хочете грати разом:

$ cat <<EOF > k.txt
1
2
3
EOF

Наведені нижче приклади розділені на 2 групи. Ті, що "працюють", і ті, що "майже" працюють. Я залишаю це, тому що часто буває так само цінно бачити, чому щось не працює, як і бачити, чому щось робить.

Представлено більшість мов сценаріїв, які я знайомий. Деякі представлені декілька разів, оскільки, як і у відомому абревіатурі, на який зазвичай посилається Perl, TIMTOWTDI .

ПРИМІТКА. Ви можете поміняти кому ( ,) у наведених нижче прикладах і замінити її будь-якими символами, які ви хочете, тобто |.

Приклади, які "працюють"

Ці фрагменти коду дадуть бажаний вихід.

pasteкоманда:

$ paste -s -d ',' k.txt 
1,2,3

sedкоманда:

$ sed ':a;N;$!ba;s/\n/,/g' k.txt
1,2,3

$ sed ':a;{N;s/\n/,/};ba' k.txt 
1,2,3

perlкоманда:

$ perl -00 -p -e 's/\n(?!$)/,/g' k.txt
1,2,3

$ perl -00 -p -e 'chomp;tr/\n/,/' k.txt
1,2,3

awkкоманда:

$ awk '{printf"%s%s",c,$0;c=","}' k.txt
1,2,3

$ awk '{printf "%s,",$0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk -vORS=, 1 k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk 'BEGIN {RS="dn"}{gsub("\n",",");print $0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

pythonкоманда:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,3

$ python -c "import sys; print sys.stdin.read().replace('\n', ',').rstrip(',')" <k.txt
1,2,3

mapfileВбудований Bash :

$ mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
1,2,3

rubyкоманда:

$ ruby -00 -pe 'gsub /\n/,",";chop' < k.txt
1,2,3

$ ruby -00 -pe '$_.chomp!"\n";$_.tr!"\n",","' k.txt
1,2,3

phpкоманда:

$ php -r 'echo strtr(chop(file_get_contents($argv[1])),"\n",",");' k.txt
1,2,3

Коваджі

Більшість наведених вище прикладів буде добре працювати. У деяких є приховані проблеми, як-от приклад PHP вище. Функція chop()фактично є псевдонімом rtrim(), тому пробіли останнього рядка також будуть видалені.

Так само це робить і перший приклад Ruby, і перший приклад Python. Проблема полягає в тому, як вони всі використовують тип операції, який, по суті, "відбиває" сліпого характеру. Це добре підходить для прикладу, який надав ОП, але слід бути обережним при використанні цих типів одних лайнерів, щоб переконатися, що вони відповідають даних, які вони обробляють.

Приклад

Скажіть наш зразок файлу, k.txtвиглядав так:

$ echo -en "1\n2\n3" > k.txt

Схоже, але це має одну незначну різницю. Він не має контуру нового рядка ( \n), як оригінальний файл. Тепер, коли ми запускаємо перший приклад Python, ми отримуємо це:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,

Приклади, які «майже» працюють

Це приклади "завжди нареченої, ніколи не нареченої" . Більшість з них, ймовірно, могли бути адаптовані, але, працюючи на потенційному вирішенні проблеми, коли вона відчувається «вимушеною», це, мабуть, неправильний інструмент для роботи!

perlкоманда:

$ perl -p -e 's/\n/,/' k.txt
1,2,3,

trкоманда:

$ tr '\n' ','  < k.txt 
1,2,3,

Команди cat+ echo:

$ echo $(cat k.txt)
1 2 3

rubyкоманда:

$ ruby -pe '$_["\n"]=","' k.txt
1,2,3,

Bash while+ readвбудовані:

$ while read line; do echo -n "$line,"; done < k.txt
1,2,3,

1
Щодо того, awkя віддаю перевагу коротшій альтернативі:awk -vORS=, 1 k.txt
маніпулювання

Не впевнений, чи має CentOS bash:mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
маніпулювання

не впевнений у прокладенні нового рядка. Згідно з моїм тестом, ваш perlі перший awkмає їх теж.
манатура

Я би поставив ту pasteсаму вгорі. Саме це і paste -sє для чого. Це стандартна команда і була б найбільш ефективною. Усі інші є надмірними та / або не портативними, або мають обмеження.
Стефан Шазелас

mapfileпорівняно новий, доданий в bash4.0.
манатство

4

@slm вже дав приємну відповідь, але як ваше питання "формат виведення xargs"

xargs -I{} echo -n "{}|" < test.txt
  • -I є опцією "замінити рядки".
  • {} є заповнювачем для вихідного тексту.
  • Це схоже на використання фігурної пари з дужками у «знаходженні».

Якщо ви хочете позбутися від останнього, |ви можете скористатись sedочищенням:

$ xargs -I{} echo -n "{}|" < k.txt  | sed -e 's/|$//'
1|2|3

Це спрацьовує додаткову трубу після 3. "1 | 2 | 3 |". У мене була та сама проблема з рішенням циклу і циклу.
slm

так, якщо є нова лінія .. tr, sedта інша також ..
Рахул Патіл

2

Це стара нитка, я знаю. ОП запитав з таким простим кодом. Щоб воно було близьким до оригіналу, у мене є просте рішення.

cat k.txt | xargs
1 2 3

використовувати sed

cat k.txt | xargs | sed 's/ /,/g'
1,2,3

або

cat k.txt | xargs | sed 's/ /|/g'
1|2|3

sed може виглядати трохи дивно, але розбитий, має багато сенсу.

's призначений для заміни. g 'є глобальним: без цього він буде робити лише першу заміну в кожному новому рядку. Оскільки ви використовуєте 'xargs', він відображає їх як один рядок. Так ви отримаєте "1,2 3".

Роздільник використовується для розділення. Я використав / символ. Один цікавий трюк: ви можете замінити роздільник на більшість будь-яких інших символів, якщо ми зберігаємо його в тому ж форматі між цитатами. Тож це також спрацювало б….

cat k.txt | xargs | sed 's# #,#g'

або

cat k.txt | xargs | sed 'sT T,Tg'

Очевидно, що використання певних знаків як роздільника може заплутатися, тому будьте розумні.


0
xargs <k.txt | tr \  \|

Вам не потрібно cat- просто введіть введення файлу і - якщо йому не надана інша команда - xargsпередасть його формат за замовчуванням - який має своєрідний тип /bin/echo's (без зворотної косої інтерпретації c-escape) .

xargsзніме пробіл голови / хвоста з вхідного файлу і видавить інші послідовності пробілів до єдиного пробілу. Це означає , що при проходженні файлу з trдо xargsяк:

tr \\n \| <k.txt | xargs

... відбитки ...

1|2|3|

... піде іншим способом і працює лише над аргументами, які xargsрозмежовує простір ....

1|2|3\n

... тому що xargsдрукує остаточний останній новий рядок (як це потрібно для текстового файлу) , але він не отримує trандиляції таким чином.

Зауважте, що це (або будь-яке інше запропоноване тут рішення) не враховує xargsцитування вхідних даних. xargsбудуть витіснятись буквально одиничними / подвійними / зворотними косими рисочками, що не містять рядків пробілів у рядку, які самі можуть бути цитовані як:

xargs <<\IN
1    2'      3'\'      \'4
IN

1 2      3' '4
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.