1

I have a text file that looks something like this

Name1 OpenFin
Name2 Chrome
Name3 OpenFin
Name4 Chrome
Name5 OpenFin
Name6 OpenFin

I want to sort this is a way where all lines with OpenFin appears first followed by all lines with Chrome

This is what I have so far:

grep OpenFin LoginExcInternal.txt | grep Chrome LoginExcInternal.txt > test.txt
  • 4
    sort -k2r LoginExternal.txt – steeldriver Mar 12 at 14:36
  • Genius! Can you explain how this works? – Ibrahim A Mar 12 at 14:38
  • I also need the names to stay in alphabetical order – Ibrahim A Mar 12 at 14:39
  • The names you have provided do stay in (lexical) order - if you have a more complex requirement, then please provide an example reflecting that. If you have GNU sort then you can try sort --stable -k2r LoginExternal.txt – steeldriver Mar 12 at 14:50
2

A direct translation of your requirement:

all lines with OpenFin appears first, followed by all lines with Chrome

... without having to know which sorts first would be:

{ grep -F OpenFin LoginExcInternal.txt; grep -F Chrome LoginExcInternal.txt; } > test.txt

This also keeps the lines in the order in which they appeared in the original file (without going through hoops to keep sort from sorting on the whole line).

1

Your command

grep OpenFin LoginExcInternal.txt | grep Chrome LoginExcInternal.txt > test.txt

would only produce the lines from the original data that contains the string Chrome anywhere on the line. This is because the result of the first grep in the pipeline would not be handled at all by the right hand side of the pipeline (it would simply be discarded).

grep will, when given a filename to read from, not process its standard input stream. It's on the standard input stream that the result of the first grep arrives.


sort -k2r LoginExcInternal.txt >test.txt

You want the lines with Chrome in their 2nd column to come after the lines containing OpenFin in the same column. The above does that by means of sorting the original data on the second column in reverse lexicographical order.

The -k2r flag to sort tells the utility to sort the data on the second column (and onwards, if there were more than two columns), in reverse order (the r). If two lines have the same value in the second column, then the whole line will be used as the sorting key.

Lines with any other values in the second column will be sorted with the rest of the lines and also be part of the output.


If you care about the original ordering of the data and don't want to change it, and assuming that you only want to extract the lines with these two values in the second column (and no other values) then do it in two steps:

awk -v value='OpenFin' '$2 == value' LoginExcInternal.txt >test.txt
awk -v value='Chrome'  '$2 == value' LoginExcInternal.txt >>test.txt

This applies the same awk code twice on the original data, with different values in the variable value. The code does a string comparison in the second column (only) and prints the lines that have the specified value. The first run of the awk script does the OpenFin values, and the second adds the Chrome lines to this.

This avoids involving the first column in the comparison of the data, which would be an issue if any of the first column's values happened to be Chrome or OpenFin. Also, since the awk code uses string comparisons, it avoids outputting lines whose second column may contain one of the strings as substring.

0

This was answered by the user "emilrn" then removed for some reason. However, their response worked perfectly.

I was told to run both of these commands:

cat LoginExcInternal.txt | grep OpenFin >> test.txt
cat LoginExcInternal.txt | grep Chrome >> test.txt

Thank you emilrn!

  • unnecessary cat. cat file | grep ... is almost always unnecessary. – Weijun Zhou Mar 12 at 18:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.