2

I have a script that is going to be executed by sh and bash on Debian Linux.

  1. When it is called by sh, the following echo command works perfectly, and replaces \t with 3 spaces. However, it fails when using #!/bin/bash.
    #/bin/sh
    echo "Hello\tworld"
    
    Output
    Hello   world
    
  2. When it is called by bash, the following echo command works perfectly, and replaces \t with 3 spaces. However, it fails when run with #/bin/sh.
    #/bin/bash
    echo -e "Hello\tworld"
    
    Output
    Hello   world
    

Is there any way where the same line command to replace \t sh or bash?

user000001
  • 3,635
  • @Theophrastus, I want to write universal a script with an echo command which can replace \t with 3 spaces, which will be executed either in bash or shell. At present script mentioned in shell does not work as expected in bash, bash script does not execute in shell as expected – Pravin.2087 Jul 18 '21 at 16:13
  • 2
    You never say how you run these scripts of yours. Note that the #!-line will be ignored as they are faulty (does not start with #!). Also note that neither command would ever output a single space! – Kusalananda Jul 18 '21 at 16:59
  • 3
    The issue is that echo is a built-in in both sh (which is usually a link to ksh) and in bash, and they are slightly differently specified. Using /bin/echo should at least be consistent. In any case, neither sh nor bash expands the TAB into three spaces: od -t a shows a Tab is output. Any expansion is done by the terminal emulator. If you echo into a file, it will be 12 bytes long (10 letters, one tab, one newline), not 14. – Paul_Pedant Jul 18 '21 at 17:24
  • @Paul_Pedant on what systems is sh a link to ksh? I've never come across that. It's a link to bash on many systems, since bash runs in compatibility mode, and it is a symlink to dash on Ubuntu and Debian and their derivatives. I don't know of any Linux that has it pointing to ksh, is that common in the UNIX world perhaps? – terdon Jul 18 '21 at 18:18
  • 1
    What do you mean by "replace \t with 3 spaces"? None of the commands you show actually replace the \t with anything. It is only that some interpret it and display it as a tab and others as a literal \ and t, but none of them convert it to spaces. Can you explain what your final objective is here? – terdon Jul 18 '21 at 18:21
  • 2
    Your premise is faulty. If you "have a script that is going to be executed by sh and bash on Debian Linux" then it's a sh script and you should mark as such with the #!/bin/sh and not call it with bash – Chris Davies Jul 18 '21 at 18:24
  • @terdon sh is ksh on OpenBSD, but that's beside the point as the OP says they are on Debian GNU/Linux. – Kusalananda Jul 18 '21 at 18:26
  • 2
    Summary: echo is like that, it behaves differently in different shells. Use printf 'Hello\tworld\n' if you want to output a tab and a newline. Like you get with Bash's echo -e, and Dash's echo , Dash being what your Debian very likely has as /bin/sh. If you really, seriously, want to output a particular number of spaces from the script, then that's not something either of those commands do. For that, you may want to ask another question. – ilkkachu Jul 18 '21 at 18:54
  • 1
    @Paul_Pedant, using /bin/echo would work the same on that particular system regardless of the shell they used, but you'd still get different results if you happened to move to another system where this time /bin/echo does things differently. Let's just, you know, not use echo at all if compatibility is an issue. – ilkkachu Jul 18 '21 at 18:59

1 Answers1

4

Assuming the tab is in the literal and not in a variable

printf 'Hello\tworld\n'

If the string is in the variable, then it is best to avoid putting the variable as the first argument of printf, because then you will need to escape any percentage marks (%) or backslashes (\ ) in the variable. The best way is to use %b as the format specifier in printf (Thanks to @Stéphane Chazelas)

$ a='hello\tworld'
$ printf "%b\n" "$a"
hello   world
$ printf "%b\n" "$a" | cat -A
hello^Iworld$
user000001
  • 3,635
  • 1
    x="Hello\tworld" y=$(printf "${x}") works in bash as well shell giving output as with echo ${y} Hello world – Pravin.2087 Jul 19 '21 at 06:02
  • @Pravin.2087 correct, but you should be careful if there are any percentage marks (%) or backslashes (\) in the variable. They will need to be escaped – user000001 Jul 19 '21 at 06:16
  • 1
    You can do printf '%b\n' "$var" for $var to undergo the same backslash expansions as standard echo implementations do. Your sed approach would turn \\t to \<Tab> – Stéphane Chazelas Jul 19 '21 at 07:23
  • @StéphaneChazelas: Thanks, that is really helpful – user000001 Jul 19 '21 at 07:30