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.

αғsнιη
  • 41,407
yisha
  • 909

14 Answers14

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.

αғsнιη
  • 41,407
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
fredtantini
  • 4,233
11

With GNU datamash:

$ datamash -W transpose <file
PAPER
TEAM
MANISH
NISHA
GARIMA
JYOUTI
cuonglm
  • 153,898
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
Avinash Raj
  • 3,703
7

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

awk '{OFS=RS;$1=$1}1' file > file2
jasonwryan
  • 73,126
  • 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 01 '22 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.

Philippos
  • 13,453
slm
  • 369,824
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

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

jubilatious1
  • 3,195
  • 8
  • 17
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
Kusalananda
  • 333,661
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
agc
  • 7,223
-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
Xplore
  • 99
-2
awk '{for (i=1;i<=NF;i++) {print($i)}}' file > File2
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255