what does " \a" do in shell substitution in shell script in linux? - shell

i read about \a escape character.
its description tells that it is basically used for alert or BEL
can anyone tell me that
is it creates some sound effect?
or please tell me any command that makes CPU to beep a sound
please tell me its necessary for me
Thanx in advanced

it echoes ASCI code 7:
$ echo -n $'\a' > file
$ od file
0000000 000007
0000001

Related

osascript 'do shell script' line endings

I'm trying to debug an larger osascript 'do shell script' program and have narrowed the problem down to a much shorter repro case that I don't understand at all. Here's the repro case:
osascript -e 'do shell script "echo 123; echo 45; echo 6"'
Gives me the output:
653
Can anybody explain what's going on? It's almost like 'do shell script' does not properly handle line endings, or tries to print everything on one line.
Applescript replaces \n characters with \r characters when reading the output of a shell script. You can tell this is happening by running the output through od -c:
$ osascript -e 'do shell script "echo 123; echo 45; echo 6"' | od -c
0000000 1 2 3 \r 4 5 \r 6 \n
0000011
To turn this off, use the without altering line endings parameter.
osascript -e 'do shell script "echo 123; echo 45; echo 6" without altering line endings'
See Technical Note TN2065 for more.

Error when using exec vi

#!/bin/bash
if [ $# -ne 1 ]
then
echo "USAGE:vitest filename"
else
FILENAME=$1
exec vi $FILENAME <<EOF
i
Line 1.
Line 2.
^[
ZZ
EOF
fi
exit 0
I'm trying to input the Line 1. and Line 2. with Exec vi using the here doc, and commands.
When running the script it gives me the following:
Vim(?):Warning: Input is not from a terminal
Vim: Error reading input, exiting...
Press ENTER or type command to continueVim: Finished.
Vim: Error reading input, exiting...
Vim: Finished.
You want to start vi in ex mode, with a few minor changes to the script.
vi -e "$FILENAME" <<EOF
i
Line 1.
Line 2.
.
wq
EOF
exec is almost certainly unnecessary, especially since you have an exit command following vi. exec is used to replace the current script with the given command; it is not needed simply to execute a command.
A brief history of UNIX text editors:
ed was the original editor, designed to work with a teletype rather than a video terminal.
ex was an extended version of ed, designed to take advantage of a video terminal.
vi was an editor that provided ex with a full-screen visual mode, in contrast with the line-oriented interface employed by ed and ex.
As suggested, ed
ed file << END
1i
line1
line2
.
wq
END
The "dot" line means "end of input".
It can be written less legibly as a one-liner
printf "%s\n" 1i "line1" "line2" . wq | ed file
Use cat.
$ cat file1.txt file2.txt | tee file3.txt
Line 1
Line 2
aaaa
bbbb
cccc
Using sed
If I understand correctly, you want to add two lines to the beginning of a file. In that case, as per Cyrus' suggestion, run:
#!/bin/bash
if [ $# -ne 1 ]
then
echo "USAGE:vitest filename"
exit 1
fi
sed -i.bak '1 s/^/line1\nline2\n/' "$1"
Notes:
When a shell variable is used, it should be in double-quotes unless you want word splitting and pathname expansion to be performed. This is important for file names, for example, as it is now common for them to contain whitespace.
It is best practice to use lower or mixed case names for shell variables. The system uses upper case names for its variables and you don't want to overwrite one of them accidentally.
In the check for the argument, the if statement should include an exit to prevent the rest of the script from being run in the case that no argument was provided. In the above, we added exit 1 which sets the exit code to 1 to signal an error.
Using vi
Let's start with this test file:
$ cat File
some line
Now, let's run vi and see what is in File afterward:
$ vi -s <(echo $'iline1\nline2\n\eZZ') File
$ cat File
line1
line2
some line
The above requires bash or similar.

Use colors when printing file content in Bash

I have a script that stores text in a file. Some of that text has bash color espcaed characters that I would like to be used when I display the content of that file in a bash shell. How can this be achieved.
Fox example, ScriptOutput.txt contains
Server is \e[92mRUNNING\e[0m
I would normally cat the file and get the content, but cat will not color the "RUNNING" section of that line in the text file. I also tried
echo $(cat ScriptOutput.txt)
but it will print everything in that file in a single line, which is useless for me. Any ideas how to print the content of that file with the colors specified in each line?
Thank you
I ended up storing the text using echo and then I cat the file line by line and print it also using echo (echo -e)
Example:
echo 'Server1 is not \e[92mAVAILABLE\e[0m' >> scriptOutput.txt
echo 'Server2 is not \e[31mNOT AVAILABLE\e[0m' >> scriptOutput.txt
cat scriptOutput.txt | while read -r line; do echo -e "$line"; done
I needed to have the script output store in a file but I also needed to print its content in the shell later on with colors. That did the trick
Thank you anyway guys
Instead of the string \e, you want to have a literal escape character in your script. How you can enter this depends on your terminal and text editor.
For me (using nano from the OS X terminal, please withhold your disdain!) I press Esc followed by Shift-V. nano tells me it's in "Verbatim Input" mode. Then I can hit the escape key and get a literal escape character (represented on screen by ^[).
This will demonstrate a universal method to insert the escape character using printf:
printf '\033[44mfoo\033[0m\nbar\n\033[92mbaz\033[0m\n' > foo.txt
cat foo.txt
You can pipe your script output through sed and replace there the '\e' character with the hex value of ESC. The result should be colored.
cat ScriptOutput.txt | sed -e 's-\\e-\x1b-g'

Is it possible to make changes to a line written to STDOUT in shell?

Is it possible to make changes to a line written to STDOUT in shell, similar to the way many programs such as scp do?
The point would be to allow me to essentially have a ticker, or a monitor of some sort, without it scrolling all over the screen.
You can manipulate the terminal with control characters and ANSI escape codes. For example \b returns the cursor one position back, and \r returns it to the beginning of the line. This can be used to make a simple ticker:
for i in $(seq 10)
do
echo -en "Progress... $i\r" # -e is needed to interpret escape codes
sleep 1
done
echo -e "\nDone."
With ANSI escape codes you can do even more, like clear part of the screen, jump to any position you want, and change the output color.
You can overwrite the last printed line by printing the \r character.
For instance this:
for i in `seq 1 10`; do
echo -n $i;
sleep 1;
echo -n -e "\r" ;
done
Will print 1 then update it with 2 and so on until 10.
You can do modify the output of stdout using another program in a pipeline. When you run the program you use | to pipe the input into the next program. The next program can do whatever it wants with the output. A general purpose program for modifying the output of a program is sed, or you could write something yourself that modifies the data from the previous program.
A shell program would be something like:
while read line; do
# do something with $line and output the results
done
so you can just:
the_original_program | the_above_program

bash tee remove color

I'm currently using the following to capture everything that goes to the terminal and throw it into a log file
exec 4<&1 5<&2 1>&2>&>(tee -a $LOG_FILE)
however, I don't want color escape codes/clutter going into the log file. so i have something like this that sorta works
exec 4<&1 5<&2 1>&2>&>(
while read -u 0; do
#to terminal
echo "$REPLY"
#to log file (color removed)
echo "$REPLY" | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' >> $LOG_FILE
done
unset REPLY #tidy
)
except read waits for carriage return which isn't ideal for some portions of the script (e.g. echo -n "..." or printf without \n).
Follow-up to Jonathan Leffler's answer:
Given the example script test.sh:
#!/bin/bash
LOG_FILE="./test.log"
echo -n >$LOG_FILE
exec 4<&1 5<&2 1>&2>&>(tee -a >(sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > $LOG_FILE))
##### ##### #####
# Main
echo "starting execution"
printf "\n\n"
echo "color test:"
echo -e "\033[0;31mhello \033[0;32mworld\033[0m!"
printf "\n\n"
echo -e "\033[0;36mEnvironment:\033[0m\n foo: cat\n bar: dog\n your wife: hot\n fix: A/C"
echo -n "Before we get started. Is the above information correct? "
read YES
echo -e "\n[READ] $YES" >> $LOG_FILE
YES=$(echo "$YES" | sed 's/^\s*//;s/\s*$//')
test ! "$(echo "$YES" | grep -iE '^y(es)?$')" && echo -e "\nExiting... :(" && exit
printf "\n\n"
#...some hundreds of lines of code later...
echo "Done!"
##### ##### #####
# End
exec 1<&4 4>&- 2<&5 5>&-
echo "Log File: $LOG_FILE"
The output to the terminal is as expected and there is no color escape codes/clutter in the log file as desired. However upon examining test.log, I do not see the [READ] ... (see line 21 of test.sh).
The log file [of my actual bash script] contains the line Log File: ... at the end of it even after closing the 4 and 5 fds. I was able to resolve the issue by putting a sleep 1 before the second exec - I assume there's a race condition or fd shenanigans to blame for it. Unfortunately for you guys, I am not able to reproduce this issue with test.sh but I'd be interested in any speculation anyone may have.
Consider using the pee program discussed in Is it possible to distribute stdin over parallel processes. It would allow you to send the log data through your sed script, while continuing to send the colours to the actual output.
One major advantage of this is that it would remove the 'execute sed once per line of log output'; that is really diabolical for performance (in terms of number of processes executed, if nothing else).
I know it's not a perfect solution, but cat -v will make non visible chars like \x1B to be converted into visible form like ^[[1;34m. The output will be messy, but it will be ascii text at least.
I use to do stuff like this by setting TERM=dumb before running my command. That pretty much removed any control characters except for tab, CR, and LF. I have no idea if this works for your situation, but it's worth a try. The problem is that you won't see color encodings on your terminal either since it's a dumb terminal.
You can also try either vis or cat (especially the -v parameter) and see if these do something for you. You'd simply put them in your pipeline like this:
exec 4<&1 5<&2 1>&2>&>(tee -a | cat -v | $LOG_FILE)
By the way, almost all terminal programs have an option to capture the input, and most clean it up for you. What platform are you on, and what type of terminal program are you using?
You could attempt to use the -n option for read. It reads in n characters instead of waiting for a new line. You could set it to one. This would increase the number of iteration the code runs, but it would not wait for newlines.
From the man:
-n NCHARS read returns after reading NCHARS characters rather than waiting for a complete line of input.
Note: I have not tested this
You can use ANSIFilter to strip or transform console output with ANSI escape sequences.
See http://www.andre-simon.de/zip/download.html#ansifilter
Might not screen -L or the script commands be viable options instead of this exec loop?

Resources