Как напечатать многострочные переменные в параллельных столбцах в bash?

12

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

varA возвращается

Aug 01
Aug 04
Aug 16
Aug 26

и varBвозвращается

04:25
07:28
03:39
10:06

если я печатаю обе переменные, он возвращает

Aug01
Aug04
Aug16
Aug26
04:25
07:28
03:39
10:06

Я хочу сделать следующее:

Aug01 04:25
Aug04 07:28
Aug16 03:39
Aug26 10:06

Я новичок в использовании Linux, и я был бы признателен за некоторые советы.

BNairb
источник
Пожалуйста, включите код bash, который вы использовали при попытке напечатать переменную two. Это так, чтобы мы могли видеть, что вы сделали неправильно в вашей попытке.
Бернард Вэй

Ответы:

22

Встречайте paste, часть предустановленных основных утилит GNU :

$ paste <(printf %s "$varA") <(printf %s "$varB")
Aug 01  04:25
Aug 04  07:28
Aug 16  03:39
Aug 26  10:06

pasteпринимает в качестве входных данных файлы, а не переменные, поэтому я использовал bashProcess Substitution и просто печатал содержимое переменной с помощью printf. Разделитель по умолчанию между столбцами TAB, вы можете изменить его с помощью -dопции, например, paste -d" "для одного символа пробела. Чтобы узнать больше о paste, посмотрите в онлайн-руководство или запустить info '(coreutils) paste invocation'.

Десерт
источник
1
@BNairb Если этот ответ решил вашу проблему, пожалуйста, найдите время и примите его , нажав на флажок слева. Это пометит вопрос как ответивший и выразит благодарность на сайтах Stack Exchange.
десерт
7

Если вы просто хотите отображать текстовые переменные рядом, у @dessert есть самое простое (лучшее?) Решение с использованием print. Однако, если вы хотите иметь возможность манипулировать каждой частью по отдельности, вы можете легко преобразовать переменные в массивы вместо этого и выполнить цикл.

#!/bin/bash

# declare the multi-line variables
var1="1
2
3
4"
var2="a
b
c
d"

# backup internal field separator to be safe
IFSave=$IFS

# set IFS to newline so vars will use newline to split into array
IFS=$'\n'

# split variables into array
foo=($var1)
bar=($var2)

#restore IFS to original value to be safe
IFS=$IFSave

# loop array foo, and cross reference key in array bar
for i in "${!foo[@]}"; do 
  printf "${foo[$i]} : ${bar[$i]}\n"
done

# you can allso now print single corresponding lines:
line=3

let id=$line-1 # arrays start at 0, so need to remove one

printf "\nPrinting line number $line\n"
printf "${foo[$id]} : ${bar[$id]}\n"
Джошуа Беснеатте
источник
4

Вы можете сделать это с помощью инструмента POSIX pr:

varA='Aug 01
Aug 04
Aug 16
Aug 26'
varB='04:25
07:28
03:39
10:06'
pr -2 -t <<eof
$varA
$varB
eof

Результат:

Aug 01                              04:25
Aug 04                              07:28
Aug 16                              03:39
Aug 26                              10:06

Или для одной вкладки:

pr -2 -t -s

Или для одного места:

pr -2 -t -s' '

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pr.html

Или с columnиз util-linuxпакета:

column -c 20 <<eof
$varA
$varB
eof
Стивен Пенни
источник
3

Если вы хотите избежать внешних утилит и сделать это непосредственно в оболочке, вы можете использовать readс отдельными дескрипторами файлов / здесь строки для каждой переменной:

while IFS= read -r -u3 a && read -r -u4 b; do 
  printf '%s\t%s\n' "$a" "$b"
done 3<<<"$varA" 4<<<"$varB"
Aug 01  04:25
Aug 04  07:28
Aug 16  03:39
Aug 26  10:06

Хотя использование оболочки для обработки текста часто считается плохой практикой, это может быть оправдано в случае, если у вас уже есть данные в переменных оболочки.

steeldriver
источник