2

Input:

hello
enrico

output:

ocirne
olleh

To do this, I can simply tac a file and pipe the output to rev (or the other way around), so one function that does the job is just this:

revtac() { tac "$@" | rev; }

Is there a built-in function for the job?

I suspect that this could potentially break something, as it would reverse <CR> and <LF> on Windows-generated files, but I'm still interested.

  • 2
    Chaining two or more tools that do their respective things well is totally in the gist of the Unix philosophy. There is no point in maintaining a single tool that does what you want, because it's easy to build it with simpler tools, ad-hoc. And you just did. – Kamil Maciorowski Jul 15 at 12:46
  • 2
    rev already breaks CRLF line endings. – ilkkachu Jul 15 at 14:22
  • @Kamil Maciorowski: And why would anyone think such a tool would be of enough value to include in a distribution? If for some reason I had to do that, I'd write a simple C program, which I could probably do much faster than posting a question and waiting for an answer. – jamesqf Jul 15 at 21:38
  • 2
    True. In fact old-school 'nix users would find that looking for a tool that does what two simple tools chained together do very well goes against the philosophy of the Unix toolbox, unless warranted by circumstance demanding a custom write. – somebody_other Jul 16 at 1:57
6

No, there's no builtin function for the job.

BTW, neither tac nor rev are builtins. They are external binary programs, some *nix systems even come without them.

You can also use Perl to simulate the combo:

perl -lne 'push @lines, scalar reverse; END { print for reverse @lines }' -- file
| improve this answer | |
  • Ok, it's clear I asked for builtins thinking that tac and rev where two builtins. What I meant is "something that I can find in bash", but you also specified that those two might not be provided on some systems. – Enrico Maria De Angelis Jul 15 at 12:44
3

you can work around with a awk or sed script depending on your real needs for example :

sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//' /path/YOURFILE | sed '1!G;h;$!d'

I tested it in that way :

$ cat /tmp/a
hello
enrico
$ sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//' /tmp/a | sed '1!G;h;$!d'
ocirne
olleh
$ 
| improve this answer | |
  • 1
    Nice, I like sed, but since it is essentially also doing the 2 step work that can be done with rev and tac, I guess there's little point in using it instead of those two. But I'll really take time to look a bit more into the first command ;) – Enrico Maria De Angelis Jul 15 at 12:58
  • 2
    @EnricoMariaDeAngelis The point is portability. sed is found on any POSIX-compliant system (or that at least tries to comply), while rev and tac aren't among the standard utilities (This does not mean that they can't be found on non-GNU/Linux systems, though). – fra-san Jul 15 at 13:14
2

Or awk:

awk '
  function rev(s,   t,i) {
    for (i = length(s); i > 0; i--)
      t = t substr(s, i, 1)
    return t
  }
  { line[NR] = rev($0) }
  END { for (i = NR; i > 0; i--) print line[i] }
' file
| improve this answer | |

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.