tags:

views:

29

answers:

2

How can I take a multi-line string in zsh, and split it into an array of strings that are a single line each?

Specifically I want to take the output of cal

      June 2010     
Su Mo Tu We Th Fr Sa
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30

and turn it into

("      June 2010     " "Su Mo Tu We Th Fr Sa" "       1  2  3  4  5"  " 6  7  8  9 10 11 12" "13 14 15 16 17 18 19" "20 21 22 23 24 25 26" "27 28 29 30")

Which is a zsh array.


My ultimate goal is then to take the output of another command and put them side by side, so if i had

a
b
c

and

d
e
f

I would end up with

a d
b e
c f
+3  A: 

Here's an example of process substitution which will work in zsh and Bash. It uses the Unix/Linux tool paste to put two calendars side-by-side as a demonstration.

$ paste <(cal 6 2009) <(cal 6 2010)

     June 2009               June 2010
Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
    1  2  3  4  5  6           1  2  3  4  5
 7  8  9 10 11 12 13     6  7  8  9 10 11 12
14 15 16 17 18 19 20    13 14 15 16 17 18 19
21 22 23 24 25 26 27    20 21 22 23 24 25 26
28 29 30                27 28 29 30

To answer your question directly:

saveIFS=$IFS; IFS=$'\n'; array=($(cal 6 2010)); IFS=$saveIFS

Which also works in Bash.

Dennis Williamson
Second semicolon may be omitted.
ZyX
+1  A: 

In zsh, you may type

array=( ${(s.
.)"$(cal)"} )

or, with eval:

eval $'array=( ${(s.\n.)"$(cal)"} )'

Here (s.smth.) specifies the expression to split on (no patterns, only fixed string. Unlike IFS, (s.:::.) will split on :::, while IFS=':::' will split on :). eval is used in order to put newline character inside (s) flag since (s.\n.) means split on backslash followed by letter «n».

ZyX
Or just `${(f)"$(cal)"}`. The `f` is the same as `ps:\n:`. The later also shows how to use “escapes” with `s` without resorting to `eval`.
Chris Johnsen
@ZyX: Your first one doesn't work for me (I get everything in one array element), unless I quote the command substitution: `"$(cat)"` the way **Chris** did in the comment above.
Dennis Williamson
@Chris Johnsen thanks, forgot about `p` and did not know about quoting. Maybe you should post your own answer?
ZyX
Err, I meant `"$(cal)"`, but you got it.
Dennis Williamson