Mike Cooper
Mike Cooper

Reputation: 3048

Split a paragraph into lines in ZSH

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

Upvotes: 3

Views: 4043

Answers (2)

ZyX
ZyX

Reputation: 53614

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».

Upvotes: 7

Dennis Williamson
Dennis Williamson

Reputation: 360035

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.

Upvotes: 6

Related Questions