how do I escape/finish this simple bash alias on Mac? - macos

What I want to achieve: I input s in the terminal, and after 25 minutes I get a notification to take a break. Here is the code:
alias s='sleep 1500 && osascript -e 'display notification "break" with title "break"''
I get an error if I include the final ', and also if I don't.

Using an alias
One can combine single-quoted strings with single quotes as follows:
$ echo 'a'\''b'
a'b
In the above, 'a' is a single-quoted string. It is followed by an escaped single-quote \' which is followed by another single-quoted string 'b'. In this way, one can build complex strings with single-quotes.
For your command, that would look like:
alias s='sleep 1500 && osascript -e '\''display notification "break" with title "break"'\'
Using a function
As #Kevin pointed out, this is simpler:
unalias s
s() { sleep 1500 && osascript -e 'display notification "break" with title "break"'; }

Related

ZSH: Escape or quote a string with backslashes

I wrote a little function, that "translates" a Windows path to a OSX path and opens it in the Finder. The function works perfectly with bash, but not with zsh (I use oh-my-zsh).
The problem is that it parses specific backslash combinations, for instance: \f, \a, \01, \02, \03, etc...
For example, this path string is the input:
"\60_Project\6038_Projekt_Part\05_development\assets\img\facebook"
After the translation function, the \f sequence (from img\facebook) is incorrectly translated as whitespace, producing the output:
"/60_Project/6038_Project_Part_developmentssets/img
acebook"
My goal is to just paste in a Windows path and not have to manually change anything.
How can I escape or quote a string with zsh, to get the result I want?
Here is the code I wrote:
function parsewinpath {
echo $1 | sed -e 's/\\/\//g'
}
function openwinpath {
echo "Opening..."
open $(parsewinpath "/Volumes/myvolume$1")
}
Usage:
openwinpath '\60_Project\6038_Project_Part\05_development\assets\img\facebook'
The result should be that the Finder opens:
/Volumes/myvolume/60_Project/6038_Project_Part/05_development/assets/img/facebook
You don't need parsewinpath at all. Just use parameter expansion to replace backslashes with forward slashes.
openwinpath /Volumes/myvolume${1//\\//}
The problem is that echo is trying to interpret escape sequences in the string as it prints it. Some versions of echo do this; some do it only if you pass the -e option; some print "-e" as part of their output; some do ... other random things. Basically, if you give echo something that contains escapes and/or starts with "-", there's no telling what it'll do.
Option 1: Use printf instead. It's a little more complicated, because you have to give it a format string as well as the actual string to be printed, but it's much more predictable. Oh, and double-quote variable references:
function parsewinpath {
printf '%s\n' "$1" | sed -e 's/\\/\//g'
}
Option 2: As #chepner pointed out, you can just skip echo, sed, and the whole mess, and use a parameter expansion to do the job:
function openwinpath {
echo "Opening..."
open "/Volumes/myvolume${1//\\//}"
}
Just escape each backslash with another backslash:
openwinpath '\\60_Project\\6038_Project_Part\\05_development\\assets\\img\\facebook'
Sorry, I know I'm 5 years late, but I thought an explanation of the problem's root and a workaround might be worth it for anyone else who ends up here:
Bash has a certain syntax. It interprets backslashes in a certain way. So you can't paste text with backslashes into the Terminal.
However, if you've copied the text to the clipboard, you may be able to circumvent bash's syntax by using a shell command to read the clipboard inside your script. So instead of using $1 to get your path from your script's argument, use pbpaste to read the clipboard directly.

Can't stuff literal $$ into gnu screen window

I am attempting to stuff a line s.a.
echo $$ | command into an existing screen window.
e.g. screen -S session -X stuff "echo $$ | command\n"
However $$ appears to already have been evaluated once it is entered into the window.
e.g. echo 7589 | command
Where 7589 is $$ of the shell executing screen -S.
Is there a way to stop the shell from evaluating $$ prior to stuffing the string?
Put single quotes around the whole thing, instead of double quotes. Double quotes still do expansion inside, single quotes don't.
BTW if you need to escape things in the middle of a string, you can break it like "foo "'something'" bar"

Jenkins text parameter - special characters garbled (unwanted variable substitution)

I have a job in Jenkins (under Linux) with build parameter of type "Text". I use the parameter to form contents of a file which is used in build process, with bash "shell execute" step like echo "$TEXTPARAM" > file.
It works quite well if there is general text. But when characters like "$" appears - it behaves strangely.
E. g. text
Some $one and $$two and $$$more bucks and $ bucks $$ that $$$ stand alone and$ after$$ words$$$
is transformed into
Some $one and $two and $-sl bucks and $ bucks $ that $$ stand alone and$ after$ words$$
though I want the text to appear in file just as it appears in input textbox.
Is it a bug in jenkins (so I should post an issue to their tracker) or am I doing something wrong?
UPDATE
I suppose that is due to variable substitution done by Jenkins. I.e all $VARNAMEs are substituted by VARNAME values prior to any "shell execute" steps are executed. And this substitution cannot be turned off as for now.
According to a comment in this ticket https://issues.jenkins-ci.org/browse/JENKINS-16143
This appears to not be a bug. Compare the parameter values $JENKINS_URL and $$JENKINS_URL.
Jenkins internally resolves placeholders in variables,
and dollars are used for that. $$ is an escaped $.
I am observing the same behavior for string and text fields on Jenkins ver. 1.562
Expansion with jenkins-cli.jar
It's true, Jenkins expands build variable names like JENKINS_URL or BUILD_NUMBER when they are prefixed by $. However, there are additional transformations—rather unexpected ones—if you use jenkins-cli.jar.
carriage return becomes \r (backslash + "r")
new line becomes \n (backslash plus + "n")
tab becomes \t (backslash plus "t")
Here is the corresponding part of the source code of jenkins-cli.jar.
I do not know any way of escaping or quoting to keep a white space character that is part of the value of a parameter for a Jenkins job when using jenkins-cli.jar
Expansion when using "raw" ssh (without jenkins-cli.jar)
The Jenkins master handles white space, backslashes and quotes on the command line somewhat like a shell:
a remains a
'a' becomes a
"a b" becomes a b
a b is an error, because the command line parser of Jenkins will see b
a" " becomes a ("a" plus space)
My idea was to re-implement the code that does the quoting in jenkins-cli.jar (minus the bugs when handling tab characters and the like). So here's my recipe:
For each argument, escape each backslash and
each single quote with a backslash.
Then surround it with single quotes.
Example: Instead of a'"b, send 'a\'"b'.
This has proven to be protect white space and quotes. And instead of using single quotes, you can use double quotes instead.
Pipeline for Testing
This is how I tested: I created the pipeline test-quoting with the string parameter "PARAM" and the following script:
import groovy.json.JsonOutput
node {
println JsonOutput.toJson(env.PARAM)
}
Then I started the pipeline (in bash), adding an additional layer of quoting that the local shell will remove:
# for testing 'a b'
$ ssh -x -p 50022 <jenkins-server> -l <user-name> build -s -v test-quoting -p PARAM="'a b'"
# for testing the behaviour of the cli with tab character
$ java -jar jenkins-cli.jar -ssh -s <jenkins-url> -user <user-name> build -s -v test-quoting -p PARAM="$(printf '\t')"
If you are unsure about what your local shell really passes to ssh (or any other command), prefix the command with strace -e execve.
This has nothing to do with Jenkins.
Write a bash script with echo "some $$$more" > file and execute that on a linux command prompt, and you will get the same gibberish.
Special characters, like $ must be escaped, since this is a linux environment and $ means a variable. There are several ways to do it.
Option 1.
Use per-character escape, i.e. for every $ that you want to appear literally, use \$ instead. So it becomes:
echo "some \$\$\$more" > file
Option 2.
Use strong-quoting, i.e. single quotes '. Nothing within single quotes has any special meaning, except for a second single quote to close the string:
echo 'some $$$more' > file
Of course with this method, you have to make sure your $TEXTPARAM string does not have any single quotes of it's own.
In either case, you will have to sanitize your input. Before you output it to file, you will need to parse the content of $TEXTPARAM and either replace all $ with \$ and use Option 1. Or parse your $TEXTPARAM and remove all single quotes ' before outputting that to file using Option 2.
Edit
In your case, I think you just want:
echo $TEXTPARAM > file without any extra quotes
root# ~ $ cat test.sh
#!/bin/bash
TEXTPARAM='Some $one and $$two and $$$more bucks and $ bucks $$ that $$$ stand alone and$ after$$ words$$$'
echo $TEXTPARAM
echo $TEXTPARAM > file
cat file
root# ~ $ ./test.sh
Some $one and $$two and $$$more bucks and $ bucks $$ that $$$ stand alone and$ after$$ words$$$
Some $one and $$two and $$$more bucks and $ bucks $$ that $$$ stand alone and$ after$$ words$$$

Using echo to pipe a string with C style comments

In my bash script I am using echo to pipe a string containing c style comments into the mail command as follows:
echo -e $EMAIL_TXT | mail -s "$SUBJECT" $RECIPIENT where $EMAIL_TXT contains
"/* some text */". In the email I am getting a list of all directories in the root since it is actually evalutating /* as all directories in root. How do I get my script to evaluate this as a string and not the actual command?
Put quotes around $EMAIL_TXT
echo "$EMAIL_TXT"
A note about -e:
-e causes escape sequences (such as \n and \t) in the arguments to echo to be converted to their corresponding characters (newline and tab, in those cases). It is not necessary if the arguments contain actual newline and tab characters, and it is probably not desirable either. Suppose, for example, that this answer were the text of the email. In that case, echo -e would convert the \n's into newlines, completely destroying the sense of the message.
bash does not convert \n into a newline, except in one specific case. So if you type:
echo "foo\nbar"
You'll see
foo\nbar
Because that is what you typed; bash does not convert the escape sequence. However, you can get bash to convert the escape sequence by using a different quotation form:
$ echo $'foo\nbar'
foo
bar
$
Of course, you can also just include a newline:
$ echo "foo
> bar"
foo
bar
$
Put quotes around the variable. I.e.
echo -e "$EMAIL_TXT" | mail -s "$SUBJECT" $RECIPIENT
Run just the echo command with and without the quotes to see the difference.

bash: capture '\*' in a command line

function abc ()
{
echo "You typed exactly this: $1"
}
Now run it:
myprompt$ abc abc\*
And I get:
You typed exactly this: abc*
I'm writing a function in which I need to capture the entire argument, including the backslash, for future use. Can it be done? I've tried every combination of quotes and 'set's and nothing keeps the backslash there. I know I can escape it, but then the argument as typed would not be identical to the argument as echoed. Note that you get the argument back perfectly via 'history'. How can I capture it inside my function, backslash and asterisk and all?
The shell interprets the \ character on the command line as an escape character that removes any special meaning from the following character. In order to have a literal \ in your command line, you need to persuade the shell to ignore the special meaning of \ which you do by putting a \ before it. Like this:
myprompt$ abc abc\\\*
Notice there are three \ characters. The first tells the shell to ignore the special meaning of the following character - which is the second \. The third \ tells the shell to ignore the special meaning of the *.
Another way to persuade the shell not to interpret the \ as an escape character is to put your argument in single quotes. Like this:
myprompt$ abc 'abc\*'
You can't get the arguments exactly as typed. Bash evaluates them before your function ever sees them. You'll have to escape or quote it.
abc abc\\*
abc 'abc\*'
You could always take the shotgun vs fly approach and implement your own shell. :)
Or tone it down a bit and find a shell that supports the input mechanism you want.
Note that you would have to change your login settings to utilize a "verbatim-shell".
All,
It looks like it is possible to capture an exact command line within a function.
As I suspected, 'history' gives us a way:
function exact_line ()
{
str1=`history 1`
str2=($str1)
str3=
# This isn't very elegant, all I want to do is remove the
# line count from the 'history' output. Tho this way I do
# have surplus spaces removed as well:
for ((i=1; ; i++))
do
str3="$str3 ${str2[$i]}"
if [ -z ${str2[$i]} ]; then break; fi
done
echo -e "Your exact command line was:\n\n$str3"
}
Thoughts? Can this be improved?

Resources