22

Suppose I have a file:

File1:

PAPER  TEAM  MANISH NISHA GARIMA JYOUTI ........etc 

File2 I want:

PAPER    
TEAM
MANISH
NISHA
GARIMA    
JYOUTI

Rows to column conversion of File1.

2

14 Answers 14

31

Using tr, replace each repeated space character( ) with a single new-line(\n) character.

tr -s ' '  '\n'< infile > outfile

But I think you want something like this?

Original Transposed
0 1 2 3
a b c d
# $ @ %

0 a #
1 b $
2 c @
3 d %

With awk we could do:

awk '{ for (i=1; i<=NF; i++) RtoC[i]= (i in RtoC?RtoC[i] OFS :"") $i; } 
    END{ for (i=1; i<=NF; i++) print RtoC[i] }' infile

This joins each same filed number positon into together and in END prints the result that would be first row in first column , second row in second column, etc. Of course the input file is limited to your memory size.

0
13

You could also use the fmt command:

~$ cat f
PAPER  TEAM  MANISH NISHA GARIMA JYOUTI
~$ fmt -1 f
PAPER
TEAM
MANISH
NISHA
GARIMA
JYOUTI
0
11

With GNU datamash:

$ datamash -W transpose <file
PAPER
TEAM
MANISH
NISHA
GARIMA
JYOUTI
1
  • datamash seems like the best tool for the task, but fascinating how many other tools could be used! Sep 19, 2018 at 20:07
10

You could simply do this through grep. By default grep, would print the match in a separate newline .

grep -oP '\S+' infile > outfile

OR

grep -o '[^[:space:]]\+' infile > outfile
0
7

Using awk, setting the output field separator (OFS) as the record (line) separator (RS):

awk '{OFS=RS;$1=$1}1' file > file2
1
  • That would set OFS to RS every time a line is read, you don't need to do that as it's inefficient, doing it once is enough - awk 'BEGIN{OFS=ORS} {$1=$1}1'. I also changed RS to ORS as it is technically the output record separator you want to use, only really matters if they're different.
    – Ed Morton
    May 1, 2022 at 13:02
6

You can also do this using sed:

$ sed -e 's/  */\n/g' file1 > file2

NOTE: Doesn't handle the situation where the words contain spaces.

1
  • 2
    This requires GNU sed, as best as I can tell. The one that ships with mac (BSD) doesn't see \n as newline Jan 14, 2020 at 15:57
1

Using a for loop:

for val in `cat file1` ; do echo $val >> file2; done;
1
awk '{for(i=1;i<=NF;i++){$i=$i"\n"}}1' file1 >file2

output

PAPER
 TEAM
 MANISH
 NISHA
 GARIMA
 JYOUTI

Second method

perl -pne "s/ /\n/g" file1 >file2

output

PAPER
TEAM
MANISH
NISHA
GARIMA
JYOUTI
1
  • Extra spaces get translated to blank lines using your Perl5 code; I think you mean s/\s+/\n/g instead. May 7, 2022 at 23:07
1

Using Raku (formerly known as Perl_6)

raku -ne '.put for .words;' 

Sample Input:

PAPER  TEAM  MANISH NISHA GARIMA JYOUTI
paper  team  manish nisha garima jyouti

Sample Output:

PAPER
TEAM
MANISH
NISHA
GARIMA
JYOUTI
paper
team
manish
nisha
garima
jyouti

Note, there seems to be some discussion that the OP doesn't want a single column as output, i.e. that this is actually a row/column transpose question. No matter, below is how you transpose whitespace-separated "columns" in Raku (e.g. capitalized first Row becomes capitalized first Column):

~$ raku -e '.put for [Z] lines.map(*.words);'  file
PAPER paper
TEAM team
MANISH manish
NISHA nisha
GARIMA garima
JYOUTI jyouti

https://raku.org

0

You can also try using sed

$ sed -i.bak s@' '@'\n'@g infile.txt

Please note that I am using @ as a separator for the substitution operation. This will also create a backup file. In case you don't need a backup remove .bak

$ sed -i s@' '@'\n'@g infile.txt
0

Python version:

python -c "import sys;lines=[l.replace(' ','\n') for l in sys.stdin.readlines()];print(''.join(lines))" < input.txt > output.txt

This uses < redirection into python's stdin from input.txt and writes to output.txt using > redirection. The one-liner itself reads in all lines from stdin into a list of strings,where all spaces are replaced with newlines, and we rebuild whole text using .join() function.

Alternative approach to avoid multiple spaces in series being replaced with newlines is to use .split() to break line into list of words. That way , we can ensure that each word is separated only by one newline

python -c "import sys;lines=['\n'.join(l.strip().split()) for l in sys.stdin.readlines()];print('\n'.join(lines))" < input.txt > output.txt
0

Using xargs, (stolen from souravc's answer):

xargs -n 1 < File1 > File2

Or if any minor reformatting is needed, use printf format strings as however might be needed:

xargs printf '%s\n' < File1 > File2
-1

My solution would be:

#!/bin/bash
cols=$(head -1 file.txt | wc -w)
for i in $(seq 1 $cols); do
cut -d ' ' -f$i file.txt | tr '\n' ' ' | sed s'/.$//'
echo
done
-2
awk '{for (i=1;i<=NF;i++) {print($i)}}' file > File2

You must log in to answer this question.

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