6

I want to know if there is an easy way to split a line in a file into multiple lines, such as this:

I have

A B C
1 2 3 4

And I want to get something like this, based on the first string of the line:

A B
A C
1 2
1 3
1 4

Basically based on the first string in the line create multiple lines with the second and third and fourth string and so on.

3 Answers 3

9

Here goes

awk '{for (i=2; i<=NF; ++i) print $1, $i}' file
A B
A C
1 2
1 3
1 4
0
2
printf %s\\n 'A B C' '1 2 3 4'|
sed -e's/\([^ ]*\)  *[^ ]*/&\n\1/;//P;D'

A B
A C
1 2
1 3
1 4

That works. It selects the first two sequences of zero or more not-space characters which are separated by one or more spaces. The first such sequence is referenced in \1 and the whole selection in &. The selection is replaced with itself followed by a \newline then \1. Pattern space is then printed up to the first occurring newline, and then the same portion is Deleted before the pattern space is recycled to the top of the script with what remains.

You can see what it does with the look command. Replace the P w/ l and put another l before the s///ubstitution...


A B C$
A B\nA C$
A C$
A C\nA$
A$
1 2 3 4$
1 2\n1 3 4$
1 3 4$
1 3\n1 4$
1 4$
1 4\n1$
1$

printf %s\\n 'A B C' '1 2 3 4'|
sed -ne:t -e'/  *[^ ]*/{s//\n&/2;P;s///;} -ett

A B
A C
1 2
1 3
1 4

It matches a pattern space with at least one sequence of space characters and any trailing not-spaces. The first substitution inserts a newline before the second occurrence of such a sequence, then Prints up to the newline, and the second substitution removes the first occurrence of that pattern - which will also now include the newline the first one appended to the tail of that sequence when operating on the second. The test branches back to the :t label each time a substitution occurs, and so sed eats pattern space a space separated field at a time.

With look again:


A B C$
A B\n C$
A C$
A C$
1 2 3 4$
1 2\n 3 4$
1 3 4$
1 3\n 4$
1 4$
1 4$
1

using bash -

    while read x ; do set $x ; first=$1 ; shift; for i in $* ; do echo $first  $1; shift; done  ; done  < /tmp/1
    A B
    A C
    1 2
    1 3
    1 4
3
  • 1
    What does set $x do? This code may work, but explaining why will help more than just dumping it. Jan 8, 2016 at 9:05
  • 1
    set is a shell builtin command. args to set are available to the shell as positional parameters - more details under the "SHELL BUILTIN COMMANDS" part of the bash manual. The script loops over lines in the input file and reads each line (eg., A B C..) and does a "set" to make these available as $1 , $2 etc. to the shell. It then loops over all the parameters ($*) and prints the first one each time followed by the the next (this is $1). shift is used to shift the parameters to the left so that $2 becomes $1, then $3 and so on.
    – jai_s
    Jan 8, 2016 at 9:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .