6

Is there any way for listing file contents in a shell window, such that characters are printed from right to left rather than as usual from the left to the right? or such that the BIDI algorithm steers line direction as per the text present?

This is relevant when working with text files belonging to RTL languages (as well as mixed LTR RTL documents) where you want to grep and search a lot without loading into an editor... editors don't like huge files...

Something around cat could be nice :)

In fact maybe I'll write something that just reverses each line and pipes to cat if nothing known exists.

muru
  • 193,181
  • 53
  • 473
  • 722
matanster
  • 2,294
  • 9
  • 36
  • 54

4 Answers4

9

The command you need is rev, e.g.:

$ rev <<<pa4080
0804ap
$ echo -e "pa4080_1\npa4080_2" | rev
1_0804ap
2_0804ap

Of course this also works with files:

$ >test echo -e "pa4080_1\npa4080_2"
$ <test rev # see annotation below
1_0804ap
2_0804ap

rev filename instead of rev <filename is possible but not preferable, as Stéphane Chazelas explains.

As part of util-linux rev is installed on every Ubuntu system by default.

This and alternative approaches can be found on HowTo: Reverse a String In Unix / Linux Shell? · nixCraft.


By the way: rev is to echo like tac is to cat, so to reverse the order of lines in a file:

$ >test echo -e "pa4080_1\npa4080_2"
$ <test tac
pa4080_2
pa4080_1
$ <test tac | rev
2_0804ap
1_0804ap
dessert
  • 39,392
  • 12
  • 115
  • 163
  • The link to the explanation of file redirection is very interesting! – Charles Green Dec 05 '17 at 16:37
  • @CharlesGreen Yes, that goes for nearly every of Chazelas' posts on U&L and is the reason I included it here. We all can only learn from him. – dessert Dec 05 '17 at 16:39
  • @dessert: Do you know about [**this effect**](https://www.ecenglish.com/learnenglish/lessons/can-you-read)? `tset` is bad idea for these examples :) – pa4080 Dec 05 '17 at 16:51
  • 1
    @pa4080 problem solved. – dessert Dec 05 '17 at 17:00
  • AFAIK for many RTL languages there's a relation between a character with its previous characters (like in Arabic where the form of a character depends on where it is on a word), so simply reversing the characters won't work – phuclv Dec 06 '17 at 03:14
  • @LưuVĩnhPhúc Copy that, but I think it's not possible to solve this problem without (really) special software – like [egmont](https://askubuntu.com/users/398785/egmont) proposes in [his answer](https://askubuntu.com/a/983542/507051) by the way. – dessert Dec 06 '17 at 09:48
3

dessert's answer already covers the utilities that can be used for the purpose of reversing text. If we wanted to use shell-only tools, we could make use of ${variable:start:offset} parameter expansion to reverse just a line first, then make a script that performs that on each line in text file.

Line can be reversed like so:

#!/bin/bash

length=${#1}
pointer=$((length-1))
while [ $pointer -ge 0  ];
do
    printf "%c" "${1:$pointer:1}"
    pointer=$((pointer-1))
done
printf "\n"

And it works like this:

$ ./reverse.sh "hello world"
dlrow olleh

To reverse each line in text file, we could do this:

#!/bin/bash
reverse_line(){
    length=${#1}
    pointer=$((length-1))
    while [ $pointer -ge 0  ];
    do
        printf "%c" "${1:$pointer:1}"
        pointer=$((pointer-1))
    done
    printf "\n"
}

while IFS= read -r line || [ -n "$line" ];
do
    reverse_line "$line"
done < "$1"

Test:

$ printf "hello world\nsecond line" > input.txt
$ ./reverse_file_lines.sh input.txt
dlrow olleh
enil dnoces

Of course, this isn't quite portable since ${var:start:offset} is bash-specific, so we could always resort to awk for portability:

awk '{for(i=length($0);i>0;i--) printf "%c",substr($0,i,1);print ""}'  input.txt
dessert
  • 39,392
  • 12
  • 115
  • 163
Sergiy Kolodyazhnyy
  • 103,293
  • 19
  • 273
  • 492
3

Take a look at the bicon tool which provides BiDi over terminal emulators.

Update:

GNOME Terminal 3.34 (in fact, VTE 0.58, and in turn all VTE-based emulators) support BiDi and automatically "flip" the order to RTL whenever needed.

There are some other emulators doing this too, e.g. Konsole and Mlterm.

For the rest, you can still use bicon.

egmont
  • 7,790
  • 1
  • 27
  • 37
1

The terminal mlterm has good features for right-to-left text. You can install it by running:

sudo apt install mlterm

It will autodetect whether to display the line in right-to-left mode or in left-to-right mode, and whether to align the text to the right or the left.

Screenshot

Flimm
  • 40,306
  • 22
  • 94
  • 154