0

everyone.

This transposing thing with specific pattern from rows to columns keep bugging me.

I'd like to change below rows into columns like,

From

20:20:10
abc_flow.out
sss_flow.out
20:20:11
bcd_flow.out
qcd_flow.out

To

20:20:10 abc_flow.out sss_flow.out
20:20:11 bcd_flow.out qcd_flow.out

Thank you!

2
  • 2
    if it is fixed number of lines, you can use pr instead of awk... also, see stackoverflow.com/help/how-to-ask .. for ex: Search, and research ...and keep track of what you find. Even if you don't find a useful answer elsewhere on the site, including links to related questions that haven't helped can help others in understanding how your question is different from the rest. Commented Mar 5, 2018 at 8:30
  • 4
    You will get a much more friendly reception and much better help here if you show what code you have tried so far and describe what problems you were having with it. Without code, your question looks like a request for free consulting and many people don't like that. Commented Mar 5, 2018 at 8:31

7 Answers 7

5

If and only if your Input_file is ditto same(identical) as shown samples then use simple xargs.

xargs -n3 <  Input_file

from man xargs:

-n max-args Use at most max-args arguments per command line. Fewer than max-args arguments will be used if the size (see the -s option) is exceeded, unless the -x option is given, in which case xargs will exit.

Sign up to request clarification or add additional context in comments.

6 Comments

the xargs -n3 is really a great answer +1! ;-)
Very nice solution!
@RavinderSingh13 Great solution. Could you please explain what is a ditto file? Thanks.
@Sergio, "ditto" means identical. RavenderSingh13 implied that this solution only works if the input file is identically formatted as the example (3 lines per record).
@Sergio, please check my edit now, added explanation for solution too now. kvantour, thanks for explaining ditto, I have added identical too in my solution's language :)
|
2

Below you find two solutions based on awk and sed. Both solutions are generic, meaning that we do not know how many records/lines are placed between two time strings recognized with regex /..:..:../:

awk :

awk 'BEGIN{ORS=OFS}/..:..:../&&(NR!=1){printf "\n"}1;END{printf "\n"}' <file>

Here we set the Output Record Separator (ORS) equal to the output field separator (OFS). This implies that by default, everything will end up on a single line. However, everytime we find a record which represents a time-string, we print a newline character.

It essentially checks if the line is a time, if so, print a newline character. For the rest it print all records in a single line (ORS=OFS :: output record separator is output field separator).

Remark: the END{printf "\n"} just prints the final newline character and is not really necessary. It depends on your requirements.

sed :

sed ':a;N;/..:..:..$/{P;D};s/\n/ /;ba' <file>

Understanding this is just pure sed wtf. The way to understand this is best done step by step:

  • :a create a label a
  • N append the new line to the pattern buffer
  • /..:..:..$/{P;D} if the pattern buffer ends with a time-string, then print the pattern buffer upto the first new-line character (P) and then delete that same part (D).
  • s/\n/ / replace the new-line character in the pattern buffer with a space.
  • ba goto label a

Since sed is invoked without -n it will, by default, print the remaining pattern buffer upon exit.

2 Comments

Nice answer+1! However note that you need to add a \n at the end of the stream generated by awk!!! awk 'BEGIN{ORS=OFS}/..:..:../&&(NR!=1){printf "\n"}{print}END{printf "\n"}' <file>
@Allan, yes you are right, I have updated the answer. However, if the output is piped into another file, the end statement is not always a requirement.
1

using this method might help you to solve issue:

echo $(cat answer.txt) | sed 's/ ([0-9]\)/\n\1/g' 

Comments

1

Two more solutions. Combining echo, cat, and sed:

echo $(cat file.txt) | sed 's/ \([0-9]\)/\n\1/g'                           

Or using paste command:

paste -d " " - - - < file.txt

By default, the paste command replaces newlines, \n, with tabs, Tab. In this case, however, we want to replace \n with a whitespace so we need -d " ". To limit the number of lines pasted each time we need the dash placeholder -. In this case we need three dashes because of the structure of the input data.

1 Comment

Could you explain the paste solution which is very nice?
1

another awk

$ awk '/[0-9:]/{if(line) print line; line=$0; next} 
               {line=line OFS $0} 
       END     {if(line) print line}' file

20:20:10 abc_flow.out sss_flow.out
20:20:11 bcd_flow.out qcd_flow.out

you can refine the regex match if necessary.

Comments

0

You can use the following sed command:

$ (tr '\n' ' ' < file; echo '' ) | sed 's/ \([0-9]\{1,2\}:[0-9]\{1,2\}:\)/\n\1/g'                                                              

Tested:

$ cat file
20:20:10
abc_flow.out
sss_flow.out
20:20:11
bcd_flow.out
qcd_flow.out
$ (tr '\n' ' ' < file; echo '' ) | sed 's/ \([0-9]\{1,2\}:[0-9]\{1,2\}:\)/\n\1/g'                                                              
20:20:10 abc_flow.out sss_flow.out
20:20:11 bcd_flow.out qcd_flow.out

Explanations:

the tr command will convert all EOL into spaces, then the sed command will just replace space followed by your timestamp by a \n followed by a backreference to your timestamp in order to separate the records on different lines.

Comments

0

The rs command is made for reshaping arrays like this. We can ask it to treat newline as separator (-e), and to reshape into an unknown number of rows each of three columns (0 3):

$ rs -e 0 3 <<END
20:20:10
abc_flow.out
sss_flow.out
20:20:11
bcd_flow.out
qcd_flow.out
END
20:20:10      abc_flow.out  sss_flow.out
20:20:11      bcd_flow.out  qcd_flow.out

We can add -C' ' and -z for more compact output:

20:20:10 abc_flow.out sss_flow.out 
20:20:11 bcd_flow.out qcd_flow.out 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.