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.

Enlico
  • 1,471
  • 16
  • 35
  • 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 '20 at 12:46
  • 2
    `rev` already breaks CRLF line endings. – ilkkachu Jul 15 '20 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 '20 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 '20 at 01:57

3 Answers3

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
choroba
  • 45,735
  • 7
  • 84
  • 110
  • 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. – Enlico Jul 15 '20 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
$ 
francois P
  • 1,219
  • 11
  • 27
  • 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 ;) – Enlico Jul 15 '20 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](https://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html) (This does not mean that they _can't_ be found on non-GNU/Linux systems, though). – fra-san Jul 15 '20 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
glenn jackman
  • 84,176
  • 15
  • 116
  • 168