2

I am using this command

cat acronyms.tex | sort -t{ -k1

to sort a file in which the format of the strings is like this

\newacronym{ex}{EX}{Expanded}

I want to sort by the content of the first pair of braces. However, some lines are like this

\newacronym[a string]{ex2}{EX2}

The command I am using is not able to distinguish between { and [, and the result is that the second string is sorted before the first.

How can I make it distinguish [ and {?

1

If there's some reason that you need to sort on just the contents of the first pair of braces, the simplest way is probably with a decorate-sort-undecorate pattern. I'm going to use sed and cut, but there are plenty of options to make this work in the shell:

sed -e 's/^\([^{]*{\([^}]*\)}\)/\2 \1/' < data|sort|cut -d' ' -f2-

The sed command replaces everything up to the end of the first pair of braces with the contents of the braces, a space, and then the original string. That can be sorted as usual. I'm then cutting the field I added at the start off again.

This will handle odd characters in the key fairly well, and uneven lengths, though spaces will be a problem, and escaped \} would be too. A different separator could be used if necessary.


If the data is:

\newacronym{A}{EX}{Expanded}
\newacronym{F}{EX}{Expanded}
\newacronym{D}{EX}{Expanded}
\newacronym{C}{EX}{Expanded}
\newacronym[abc]{B}{EX}{Expanded}
\newacronym{CD}{EX}{Expanded}
\newacronym[def]{E}{EX}{Expanded}

then the sed command results in:

A \newacronym{A}{EX}{Expanded}
F \newacronym{F}{EX}{Expanded}
D \newacronym{D}{EX}{Expanded}
C \newacronym{C}{EX}{Expanded}
B \newacronym[abc]{B}{EX}{Expanded}
CD \newacronym{CD}{EX}{Expanded}
E \newacronym[def]{E}{EX}{Expanded}

and the rest is straightforward.

  • Looks like the [] part of newacronym can also contain braces, eg \newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second} – meuh Sep 7 '17 at 8:06
  • Yes, extra braces could be anywhere (even inside the first pair). At that point you just need to use a proper parser. There's no way to balance them otherwise. – Michael Homer Sep 7 '17 at 8:12
1

Using -k1 will make sort use the whole line as the sort key. This is not what you want.

I'm assuming that you'd like to use ex and ex2 (as found within {...}) as the key. To do this, specify -k2 as the sort field.

This will pick up everything after the first { and use that as the key.

\newacronym{ex}{EX}{Expanded}
^^^^^^^^^^^ ^^^ ^^^ ^^^^^^^^^
field 1     f2  f3  field 4

\newacronym[a string]{ex2}{EX2}
^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^^^
field 1               f2   f3

To only use the second field as the key (not the rest of the line), use -k2,2.

Testing:

$ sort -t '{' -k2,2 file
\newacronym[a string]{ex2}{EX2}
\newacronym{ex}{EX}{Expanded}

The line still comes out in the wrong order. This is because ex2} sorts before ex} (} comes after 2 in the ASCII table, and I'm using the POSIX locale).

Trying again, but this time on Ubuntu with the en_US.UTF-8 locale (should work on any glibc Linux and in most locales except the C or POSIX locales):

$ LC_COLLATE="en_US.UTF-8" sort -t '{' -k2,2 file
\newacronym{ex}{EX}{Expanded}
\newacronym[a string]{ex2}{EX2}

Depending on your locale settings, you may or may not have to add the LC_COLLATE=... bit.


Note that sort is a separate utility from the bash shell, and that it works the same way regardless of shell. This is therefore not a "bash sort" question, just a sort question.

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.