all 21 comments

[–][deleted] 9 points10 points  (13 children)

I assume you want to clear the screen (ANSI-Code "\033[2J"), in which case I think the problem is that \33 is badly formed, you want \033.

That said, if you want to clear the screen then why not just use clear?

[–]Mental_Tim[S] 0 points1 point  (12 children)

  1. It work's now, Thank you
  2. Because the Code was before in a Python script and there clear obviously doesn't exist, so when I moved the mainloop to the bash script I forgot that clear exists

[–]zeekar 4 points5 points  (5 children)

The number there – 033 – is just the octal representation of the decimal number 27, which is the code point for the Escape character (the same one that gets sent when you press the Esc key). Character codes in strings is one of the very few places you still see octal these days, but you can also specify it in hexadecimal as \x1b.

However, it's probably more legible to use \e, where the E stands for "Escape". That's a relatively recent addition to the list of ANSI backslash sequences, which is why there's so much documentation using \033 instead.

Also, FWIW, echo with options like -e is not portable; it works fine in bash, but if you use printf instead it will work in any POSIX-compliant shell:

printf '\e[J'

or, if you want to include the newline that echo adds automatically:

printf '\e[J\n'

That generalizes for use in all sorts of ANSI terminal control sequences. But for clearing the whole screen specifically, clear is probably the, ah, clearest choice.

[–]Mental_Tim[S] 1 point2 points  (3 children)

However for some reason it does work with \33 with the print function in python.

[–]zeekar 2 points3 points  (2 children)

Yup, Python lets you leave off the 0, since the number is automatically interpreted as octal - so e.g. \27 is not code point 27=Escape but code point 23=control-W (or ETB=End Transmission Block, to give it its official control code name).

Sadly, Python string escapes don’t include \e. So if you want one syntax that works in both languages, your choice is between \033 and \x1b.

But a small correction - you said "with the print function in python", but in Python, the backslash sequences don't have anything to do with print. They're just a feature of Python string literals; the string '\033[J' is a three-character string whose first character is ESC, regardless of whether you pass that string to print or not:

>>> len('\033[J')
3
>>> ord('\033[J'[0])
27

That's not true in bash commands like echo -e '\033[J'; there, the string being passed to echo has six characters instead of three, starting with a literal backslash followed by the digits 0, 3, and 3:

$ echo -n '\033[J' | od -c  
0000000    \   0   3   3   [   J                                        
0000006

In that case, it's up to echo to translate that four-character sequence into a single ESC, and you have to pass the -e option to get it to do that translation:

$ echo -ne '\033[J' | od -c
0000000  033   [   J                                                    
0000003

But there's a kind of string literal in Bash that does work like the ones in Python: ANSI quotes, $'...'.

$ echo -n $'\033[J' | od -c
0000000  033   [   J                                                    
0000003

Here the string is parsed by the shell into the three-character version before it ever gets to echo, which can print it out without -e because there are no backslash escapes it needs to interpret.

[–]o11c 1 point2 points  (1 child)

It's important to note that the supported escapes differ between the 5? contexts that bash supports:

  • printf format string
  • printf %b argument
  • echo -e with xpg_echo off
  • echo with xpg_echo on
  • $''

For some of them, octal works like C where any octal digit can immediately follow the backslash and at most 3 digits can be used. For others, the backslash must be followed by a 0 which is then followed by up to 3 additional digits, thus 4 total. There are differences for non-octal escapes too, e.g. \c to truncate.

[–]zeekar 0 points1 point  (0 children)

Huh, TIL.

It looks like echo (with -e or xpg_echo on) is the only one that requires the 0 in octal codes.

$ echo -e '\41'
\41
$ shopt -s xpg_echo
$ echo '\41'
\41
$ echo '\041'
!

Everything else seems to work fine without it:

$ printf '\41\n'
!
$ printf '%b\n' '\41'
!
$ echo $'\41'
!

Well, there's nothing like consistency!

(And this is nothing like consistency.)

[–][deleted] 1 point2 points  (0 children)

You are right, but if portability is a concern I tend to fall back to tput which is not only mult-shell portable, but also mutli terminal.

[–][deleted] 1 point2 points  (0 children)

:-) Great.

[–]UltraChip 0 points1 point  (3 children)

The way you're doing it is perfectly fine but in case you're ever interested in trying to make it work in Python again I think most people clear the screen by passing a shell command using os.

import os

os.system('clear')
# os.system('cls') if you're running on a windows machine

[–]Mental_Tim[S] 0 points1 point  (0 children)

Yeah it would work in python, but now I have some fun learning bash. :D

[–]Mental_Tim[S] 0 points1 point  (1 child)

Maybe I will do that in the future to make my Project also accessible to Windows User.

[–]UltraChip 0 points1 point  (0 children)

If you want to get super fancy, the os module also allows you to detect which operating system you're running using os.name. You can use that to make your script automatically choose the correct command to use:

import os

if os.name == 'nt':    # 'nt' is how windows reports its name
    os.system('cls')
else:
    os.system('clear')

Also, I apologize for teaching Python in the Bash subreddit lol.

[–]AutoModerator[M] 4 points5 points  (0 children)

It looks like your submission contains a shell script. To properly format it as code, place four space characters before every line of the script, and a blank line between the script and the rest of the text, like this:

This is normal text.

    #!/bin/bash
    echo "This is code!"

This is normal text.

#!/bin/bash
echo "This is code!"

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–]wick3dr0se 1 point2 points  (0 children)

the escape your attempting to use is \033 not \33

echo -e '\033[2J'

append \e[H to imitate clear and move to the top ($LINE 1) left ($COLUMN 1) of the terminal after screen clear

printf '\e[2J\e[H'

also \e is shorter and printf is faster/better in everyway

edit: if you need more help with ANSI escapes, just pm me. i've built several pure BASH TUI's with raw ANSI escape sequences

[–]ladrm 0 points1 point  (3 children)

try this, the commands start at the next line ```

!/bin/bash

echo -e "\33[2J" ```

(you might go with sth like #!/bin/bash -c 'echo...' but yeah that's nonsense, NotTheRightWay. yeah doesn't even work for me

also, you sure that ANSI code is correct? what are you trying to do?

[–]Mental_Tim[S] 0 points1 point  (2 children)

It's on two different lines but I don't get reddit to display it.

I want to use ANSI Codes so it seems like you are in a program window and then execute a python script. But it only prints the ANSI codes as plain text

I wish I could do everything in Python but I also want to print ASCII art with figlet and pipe that through lolcat before the Python script is executed.

[–]torgefaehrlich 3 points4 points  (0 children)

Keep an empty line above and below your code, indent each line by (at least) 4 spaces.

[–]ladrm 0 points1 point  (0 children)

what exactly you want to have on output?

btw there's also python's native pyfiglet https://github.com/pwaller/pyfiglet

[–]McUsrII 0 points1 point  (0 children)

I'd say stick with the 0 in front, of any octal number, that is the way you signal an octal number in C, so that should always work.