3

I am writing a bash script in which I need color output. I have a text file that needs to be formatted like this when it's printed to the screen:

>Barry's Whiskey Glass Drink Cup, XL 10 oz Dri...        $0.75
example.org/product-page.php?id=1228741

>Cotton Bath Towel Pool Towel Brown - Easy Car...        $6.11  
example.org/product-page.php?id=1228763

>Cotton Bath Towel Pool Towel Red - Easy Care ...        $6.11     
example.org/product-page.php?id=1228766

>Mosiso MacBook Case for iPad Pro 12.9/MacBook...        $1.95  
example.org/product-page.php?id=1228850

The '>....." text needs to be one color, '$..." another color, and "example.org...." light grey. I have tried this:

  tac newlist.txt | sed 's/ >/\r\n   >/' > bwtext.txt

  sed -i 's/>/>\\033\[0;34m/g' bwtext.txt
  sed -i 's/\$/\$\\033\[0;33m/g' bwtext.txt
  sed -i 's/http/\\033\[0;37mhttp/g' bwtext.txt

  while read line
     do
        echo -e "${line}"
     done < bwtext.txt

That inserts the correct escape codes into the file, but when echoed out line by line, instead of processing the codes, it just prints them literally.

>033[0;34mFor Fitbit Alta Accessory Band, Silicone Repl...        $033[0;33m1.97      
033[0;37mexample.org/product-page.php?id=1247364

>033[0;34mTattify Gradient Nail Wraps - Love Like a Sun...        $033[0;33m0.99      
033[0;37mexample.org/product-page.php?id=1247367

>033[0;34mEA AromaCare Eucalyptus Essential Oil 120ml/4...        $033[0;33m3.00      
033[0;37mexample.org/product-page.php?id=1247370

... waiting 10 minutes for next update ...

What am I doing wrong, or how can I do it right? Thanks.

0

4 Answers 4

2

You have correct escape sequences in file but those are not being read in your while loop. Try adding raw input flag ( -r ) while reading which will not interpret the escape sequences and give you desired formatting.

while read -r line
do
echo -e "${line}"
done < bwtext.txt
Sign up to request clarification or add additional context in comments.

2 Comments

This is a good point. :-), but he can do it without introducing escape sequences to the text file. Also you might wish to add a link to the reference.
echo -e is actually contrary to POSIX -- not just an extension, but doing anything other than printing -e on output when echo is given -e on its command line contravenes standard-mandated behavior. Consequently, bash will stop honoring this if the posix and xpg_echo flags are set. The standards-compliant alternative is printf '%b\n' "$line". See pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html, particularly the APPLICATION USAGE section.
2

You might not want to introduce control characters to a plain text file. See [ exploits of a mom ].
Below could be one approach solving your problem without sed.

 #Adding color to bash script output
 while read -r line # -r to prevent mangling of literal backslashes
 do
    printf '%b\n' "${line/#>/\\e[1;34m>}" #using shell parameter expansion See Ref 2
   #Also, you need two `\` make one `\` in the substitution
    printf '%b\n' "\e[0;m" #resetting color to defaults, this is important
 done<your_actual_file

References

  1. Bash: [ Using Colors ].
  2. Shell parameter [ expansion ].
  3. In some shells which conform to POSIX standards, echo ie by default echo -e. You can neglect this point for bash. Check [ this ] for more info. Anyways I have replaced echo -e with printf '%b\n'.

Note: This answer doesn't completely satisfy your requirement but just shows you an alternate way of doing things.

4 Comments

Consider showcasing printf '%b\n' rather than echo -e, to behave properly on POSIX-compliant shells. (Also, with xpg_echo and posix flags set, even bash doesn't honor echo -e).
Also, make it while read -r line to avoid consuming literal backslashes, which prevents them from being honored in format strings.
@CharlesDuffy : Opinion honoured. :-)
More generally, while read [ -r ] to perform a text transformation on the lines you are reading is an antipattern which usually begs for a sed or Awk solution instead. There is a legitimate use for while read but that basically revolves around reading file names for Bash to operate on.
0

Where you see 033 you need to have a literal escape character. Your sed and/or echo -e can probably do this, but they are not standardized in this particular regard, and without detailed information about your system, we cannot tell you exactly how to fix the script. But you could move to a reasonably standardized tool such as Perl;

perl -pe 's/ >/\r\n   >/;
    s/>/>\033[0;34m/g;
    s/\$/\$\033[0;33m/g;
    s/http/\033[0;37mhttp/g' newlist.txt

Incidentally, sed supports putting multiple commands in a script, just like Perl. Even if you could not do that, putting the commands in a pipeline would be hugely more efficient than repeatedly rewriting the same file with sed -i.

(Also, [ is just a normal character in the substitution string, and does not need to be backslashed. In the match part, the argument is a regular expression, where of course [ has a special meaning. So in other words, in s/regex/string/ the regex and string parts are governed by slightly different syntax.)

Comments

0

I want to thank all of you for your help. I will keep both the -r switch in read and the printf instead of echo suggestion in mind for future reference. I had also posted this to an Ubuntu Forum where I was supplied with another option that has worked well:

tac newlist.txt | sed 's/ >/\r\n   >/' > reversed.txt

sed $"s/\(>[^$]*\)\($.*\)/$DESC\1$COST\2/" reversed.txt | sed $"s/\(http.*\)/$LINK\1$CLR/" | sed $"s/\(FREE\)/$FREE\1$CLR/"

Again, thank you all!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.