Làm cách nào để in các biến đa dòng trong các cột cạnh nhau (bash)?


11

Tôi có hai biến chứa thông tin đa dòng và tôi muốn cột chúng.

varA trả lại

Aug 01
Aug 04
Aug 16
Aug 26

varBtrả lại

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

nếu tôi in cả hai biến, nó sẽ trả về

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

Những gì tôi muốn làm là như sau:

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

Tôi là người mới trong Linux và tôi sẽ đánh giá cao một số lời khuyên, cảm ơn.


Vui lòng bao gồm mã bash bạn đã sử dụng để thử in hai biến. Đó là để chúng tôi có thể thấy những gì bạn đã làm sai trong nỗ lực của bạn.
Bernard Wei

Câu trả lời:


22

Gặp gỡ paste, một phần của các tiện ích cốt lõi GNU được cài đặt sẵn :

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

pastelấy tệp chứ không phải biến làm đầu vào, vì vậy tôi đã sử dụng bashThay thế quy trình và chỉ in nội dung biến với printf. Dấu phân cách mặc định giữa các cột là TAB, bạn có thể thay đổi -dtùy chọn đó, ví dụ paste -d" "cho một ký tự khoảng trắng. Để tìm hiểu thêm về pastehãy xem hướng dẫn trực tuyến hoặc chạy info '(coreutils) paste invocation'.


1
@BNairb Nếu câu trả lời này giải quyết được vấn đề của bạn, vui lòng dành chút thời gian và chấp nhận nó bằng cách nhấp vào dấu kiểm bên trái. Điều đó sẽ đánh dấu câu hỏi là đã trả lời và là cách cảm ơn được thể hiện trên các trang web Stack Exchange.
tráng miệng

7

Nếu bạn chỉ muốn hiển thị các biến văn bản cạnh nhau, @datcher có giải pháp đơn giản nhất (tốt nhất?) Bằng cách sử dụng print. Tuy nhiên, nếu bạn muốn có thể thao tác từng phần riêng lẻ, bạn có thể dễ dàng chuyển đổi các vars thành mảng thay thế và lặp qua đó.

#!/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"

3

Nếu bạn muốn tránh các tiện ích bên ngoài và thực hiện nó trong shell, bạn có thể sử dụng readvới các chuỗi mô tả tệp / chuỗi ở đây cho mỗi biến:

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

Mặc dù nó thường được coi là thực hành xấu khi sử dụng shell để xử lý văn bản, nhưng nó có thể được miễn trong trường hợp bạn đã có dữ liệu trong các biến shell.


3

Bạn có thể làm điều này với công cụ 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

Kết quả:

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

Hoặc cho một tab duy nhất:

pr -2 -t -s

Hoặc cho không gian duy nhất:

pr -2 -t -s' '

http://pub.opengroup.org/onlinepub/9699919799/utilities/pr.html

Hoặc với columntừ util-linuxgói:

column -c 20 <<eof
$varA
$varB
eof
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.