How can i reoder lines in a text file based on a pattern?

sort and save file unix
how to sort file in linux
how can we sort the data in the month wise in unix
man sort
sort options
cat, sort
what are filters explain sort with all the options available
sort numerically linux

I have a text file that contains batches of 4 lines, the first line of each batch is in the correct position however the next 3 lines are not always in the correct order.

name cat
label 4
total 5
value 4

name dog
total 4
label 3
value 6

name cow
value 6
total 1
label 4

name fish
total 3
label 5
value 6

I would like each 4 line batch to be in the following format:

name cat
value 4
total 5
label 4

so the output would be:

name cat
value 4
total 5
label 4

name dog
value 6
total 4
label 3

name cow
value 6
total 1
label 4

name fish
value 6
total 3
label 5

The file contains thousands of lines in total, so i would like to build a command that can deal with all potential orders of the 3 lines and re-arrange them if not in the correct format.

I am aware i can use awk to search lines that begin with a particular string and them re-arrange them:

awk '$1 == "value" { print $3, $4, $1, $2; next; } 1' 

However i can not figure out how to acheive something similiar that processes over multiple lines.

How can i acheive this?

Could you please try following.

awk '
/^name/{
  if(name){
    print name ORS array["value"] ORS array["total"] ORS array["label"] ORS
    delete array
  }
  name=$0
  next
}
{
  array[$1]=$0
}
END{
  print name ORS array["value"] ORS array["total"] ORS array["label"]
}
'  Input_file


EDIT: Adding refined solution of above suggested by Kvantour sir.

awk -v OFS="\n" '
(!NF) && ("name" in a){
  print a["name"],a["value"],a["total"],a["label"] ORS
  delete a
  next
}
{
  a[$1]=$0
}
END{
  print a["name"],a["value"],a["total"],a["label"]
}
'  Input_file

rearrange the data based on a pattern, You could leave the lines starting with A1 as is and re-arrange those starting with B1 # if -E or -r is not supported: sed 's/\(B1:.*\)\(A1:.*\)/\2 \1/'� Based on these criteria the first two lines in the text file are the only two lines we’re looking for: they both begin with a number and then have GRP in the fifth, sixth, and seventh character spots. Granted, Line 3 has GRP in the designated spot; however, line 3 doesn’t begin with a number.

By setting RS to the empty string, each block of text separated by at least one empty line, is considered a single record. From there it's easy to capture each key-value pair and output them in the desired order.

BEGIN {RS=""}
{
    for (i=1; i<=NF; i+=2) a[$i] = $(i+1)
    print "name", a["name"] ORS \
          "value", a["value"] ORS \
          "total", a["total"] ORS \
          "label", a["label"] ORS
}


$ awk -f a.awk file
name cat
value 4
total 5
label 4

name dog
value 6
total 4
label 3

name cow
value 6
total 1
label 4

name fish
value 6
total 3
label 5

Sorting one file line by line based on another file, I'm trying to sort the rows of a text file based on an 'index' in another file, such that the text file is arranged, row by row, in the same order as the� A Python program can read a text file using the built-in open() function. For example, the Python 3 program below opens lorem.txt for reading in text mode, reads the contents into a string variable named contents, closes the file, and prints the data.

The simplest way is the following:

awk 'BEGIN{RS=""; ORS="\n\n"; FS=OFS="\n"}
     { for(i=1;i<=NF;++i) { k=substr($i,1,index($i," ")-1); a[k]=$i } }
     { print a["name"],a["value"],a["total"],a["label"] }' file

How does this work?

Awk knows the concept records and fields. Files are split in records where consecutive records are split by the record separator RS. Each record is split in fields, where consecutive fields are split by the field separator FS. By default, the record separator RS is set to be the <newline> character (\n) and thus each record is a line. The record separator has the following definition:

RS: The first character of the string value of RS shall be the input record separator; a <newline> by default. If RS contains more than one character, the results are unspecified. If RS is null, then records are separated by sequences consisting of a <newline> plus one or more blank lines, leading or trailing blank lines shall not result in empty records at the beginning or end of the input, and a <newline> shall always be a field separator, no matter what the value of FS is.

So with the file format you give, we can define the records based on RS="" and the field separator `FS="\n".

Each record looks simplified as:

key1 string1      << field $1
key2 string2      << field $2
key3 string3      << field $3
key4 string4      << field $4
...
keyNF stringNF    << field $NF

When awk reads a record, we first parse it by storing all key-value pairs in an array a. Afterwards, we ask to print the values we find interesting. For this, we need to define the output-field-separators OFS and output-record-separator ORS.

Sorting, First and Last Lines – A Primer for Computational Biology, To answer this question, we could consider sorting the lines according to this seventh Enter sort , which s orts lines from a text file (or from standard input) by � SED is a stream editor that performs basic text filtering and transformations on an input stream (a file or input from a pipeline). Delete Lines Matching a Specific Pattern in a File using SED. In our previous guide, we covered how to delete lines matching specific patterns in VIM. You can check by following the link below;

In Vim you could sort the file in sections using reverse order sort!:

for i in range(1,line("$"))
  /^name/+1,/^name/+3sort!
endfor

Same command issued from the shell:

$ ex -s '+for i in range(1,line("$"))|/^name/+1,/^name/+3sort!|endfor' '+%p' '+q!' inputfile

Linux sort command - Sort lines of text files, Even the words beginning with same alphabet were sorted according to succeeding alphabets. 4. Use sort to directly write data in sorted manner. The Select-String cmdlet searches for text and text patterns in input strings and files. You can use Select-String similar to grep in UNIX or findstr.exe in Windows. Select-String is based on lines of text. By default, Select-String finds the first match in each line and, for each match, it displays the file name, line number, and all text in the line containing the match. You can direct

SORT command in Linux/Unix with examples, SORT command sorts the contents of a text file, line by line. sort is a Sorting is done based on one or more sort keys extracted from each line� Notice that the eighth element is misplaced. All I am doing is to streamline the line. The problem is there are 121 fields and so I am not able to use concise AWK commands to do this text manipulation in single line for the whole file. I have tried the below and it is working. Can you suggest a more efficient or more readable solution?

Awk one-liners and scripts to help you sort text files, Awk one-liners and scripts to help you sort text files Awk is the ubiquitous Unix command for scanning and processing text containing predictable patterns. In this example, the data is delimited by two factors: lines and fields. Defining the built-in variable FS, which stands for field separator and is the� This makes the lines random and can be useful for programming applications. For example, you could want to shuffle the lines of a text file randomly and creat a new file. The file could have several thousands of lines. See the example. Input data; This is line one. This is line two. This is line three. This is line four. Output: This is line two.

Sort lines of a text file, The sort command is used to sort the lines of a text file in Linux. You can provide several command line options for sorting data in a text file. Here is an example� Sort Text Lines. Sort by delimiter Big File Tool - Sort Lines. Tools provided as-is, without warranty of any kind and used at your own risk. ©2015 TextMechanic

Comments
  • This is a good solution, I would only change the printing not based on /name/ but based on an empty line. Something like ($NF==0) && ("name" in a) { print array["name"] ORS array["value"] ORS array["total"] ORS array["label"] ORS; delete array; next } this makes it a bit shorter, and more readable and more generic (assume name is not the first entry)
  • In golf, it would look like awk -v OFS="\n" '(!NF) && ("name" in a) { print a["name"],a["value"],a["total"],a["label"] ORS; delete a;next}{a[$1]=$0}END { print a["name"],a["value"],a["total"],a["label"] }' file
  • you can remove the OFS and just use a , instead. The print statement replaces the , with OFS
  • Hi Kvantour, if I may ask you,how about this solution stackoverflow.com/a/59791392/5866580 IMHO this also looks simpler, whats your opinion?
  • @RavinderSingh13 I commented on it. I believe your solution is indeed simpler. I just like exploiting the natural features of awk.