How do I prevent zsh from replacing "%5D" with "]"? - shell

[EDIT] Solved.
The actual issue was a typo in one of the handler variables, and not a zsh issue, as I initially thought.
I am trying to prevent zsh from replacing the code "%5D" for the ] right square bracket with the actual character "]".
For my purposes - calling the last.fm API via curl in shell script, to get info about a track from Apple Music - it needs to stay as "%5D", because otherwise the API doesn't recognise it.
I have tried escaping the "%5D" with backslashes or a second "%" but that doesn't work, it still gets replaced with "]"
Here's an example of what I'm trying to do and what is not working:
The original string of the track's name:
"YESTODAY (Extended Version) [Bonus Track]"
How it needs to be spelled for the API to work:
"YESTODAY+(Extended+Version)+%5BBonus+Track%5D"
The whitespaces get replaced with "+" by my AppleScript handler.
The left [ stays as "%5B" (I guess because it is immediately followed by more letters and therefore zsh cannot recognise it as code and replace it).
The right ] is generally the last character of the track string, not followed by anything and thus "%5D" is recognised by zsh and written as "]" .
How do I fix this?
Any help is greatly appreciated :)
For reference:
The part of the AppleScript that is supposed to replace the "[ ]" with code.
(This is obviously not the complete script). If you run this, it replaces the [ ] correctly. The issue only arises once the entire API call is made with do shell script curl_command because of zsh interpreting the code.
set trackreplace to "YESTODAY (Extended Version) [Bonus Track]"
if trackreplace contains "[" then
set trackreplace to replaceChars("[", "%5B", trackreplace)
end if
if trackreplace contains "]" then
set trackeplace to replaceChars("]", "%5D", trackreplace)
end if
on replaceChars(find, replace, subject)
set savedelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to find
set subject to text items of subject
set AppleScript's text item delimiters to replace
set subject to (subject as string)
set AppleScript's text item delimiters to savedelims
return subject
end replaceChars

It was not a zsh issue but actually just a typo in one of the handler variables (trackeplace instead of trackreplace), as pointed out by #GordonDavisson

Related

Search string for trailing quote character and trim it?

I'm trying to search a string (entered by the user when prompted for a path) for a trailing quote and delete it if found.
The problem: I have a bat file that prompts the user to enter a filename and path (the first is typically done via drag/drop.) If the user enters a destination path enclosed in quotes because it contains spaces, my resulting command will look like this: compress.exe "c:\source path\"destination.zip"
That extra quote in the middle needs to go. I've found plenty of ways to search a file for a string, and I found this post here on StackOverflow that seems to apply, but doesn't seem to work in my situation.
I tried the command at the above linked path, telling it to search for \" instead of bcd, but the code expects the string it's searching to have been passed to it (as a switch) upon execution, and when I try to modify the command to search srcpath instead, the bat fails. I also tried this:
if "!srcpath:~-1"=="\"" set srcpath=!srcpath:~0,-1!
This results in: "The syntax of the command is incorrect."
How can I search a string for a trailing quote and trim it? Every method I can find doesn't seem to work when the character being searched for is the quote (slash quote: \").
I use a SLOPPY batch trick when working with paths just for this reason.
There are more elegant ways but this works just as well and I don't ever have to remember how I pulled it off.
First of all, 90% of the time.. we just want ALL quotes stripped.. that would just be:
set srcpath=%srcpath:"=%
Then tack quotes on to the front and back of your new concatenated path string.
But if you REALLY only want the trailing one.. here is my stupid bash trick..
1. Add a "? to the end of your string
2. Then delete ""? from that string
3. Then delete "? from that string
Wella! Never fails!
The trick here is that a question mark isn't a valid path char.
:: SAMPLE -- Just a trailing quote removed
set srcpath="c:\source path\"
set srcpath=%srcpath%"?
set srcpath=%srcpath:""?=%
set srcpath=%srcpath:"?=%
echo srcpath=%srcpath%
::You can use the SAME TRICK to remove a trailing backslash
Would this work for you?
SET /P "%SRCPATH=Enter the source path "
ECHO %SRCPATH%
ECHO %SRCPATH:"=%

Bash/Osascript Error: unexpected EOF while looking for matching `)'

I'm splitting a string using osascript (was working this way, not with bash), and assigning the resulting array to a bash variable, and continuing with my bash script. I'm doing it like so:
tempArrayApplications=$(osascript >/dev/null <<EOF
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to "/"
set theArray to every text item of "$noSplitString"
set AppleScript's text item delimiters to oldDelimiters
return theArray
EOF)
However, the command line returns the error that it went to the end of the file without finding the matching ')'. However, when I don't assign a bash variable to the osascript output, everything works fine, so I know it's not a problem with the AppleScript section. I ran shellcheck, and it doesn't detect any errors, and the other solutions seem to be related to an unclosed quote or unescaped character, but I don't seem to have that problem. Clearly it's due to trying to assign it to a bash variable, but for the life of me I don't know what I'm doing wrong. Thanks for the help.
Have you paused to consider that you're taking a bash variable ($noSplitString); inserting this into an AppleScript that splits the text using / as the delimiter; executing this AppleScript inside a bash command (osascript); then storing its output (which actually gets destroyed) in another bash variable ($tempArrayApplications)...?
My inclination would be to remove the AppleScript altogether (3 out of its 5 lines are redundant, anyway), and create the array from the string within bash.
So, given this:
noSplitString="item 1/item 2/item 3"
Then simply do this:
IFS='/'
tempArrayApplications=($noSplitString)
Now $tempArrayApplications will be an array with three items, starting at index 0 and ending at index 2. You can echo a specific element in the array like this:
echo "${tempArrayApplications[1]}" # "item 2"
IFS is the bash equivalent of the AppleScript text item delimiters. It typically has a default value of ⎵\t\n (where ⎵ indicates a space character). More can be read about it in this article: Bash IFS: its Definition, Viewing it and Modifying it

Trouble understanding a bash command

I'm trying to set up a program and came across this line in a bash script. Could someone tell me what it does? I'm not very experienced with bash.
export PS1='\e[0;33mmyProject \e[0;32m\[\e]0;\u#\h: \w\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$\e[0m '
Thank you very much!
This command does two things. It sets the title of the terminal window, and
sets the bash prompt.
export PS1='\e[0;33mmyProject \e[0;32m\[\e]0;\u#\h: \w\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$\e[0m '
Piece by piece:
export PS1=
This sets the PS1 variable, which is contains the bash prompt.
\e[0;33m
\e is translated to the ESC character (ascii=0x1B), which is a Control Sequence Introducer, which signifies the beginning of an ANSI Escape Code. The m character at the end of the sequence indicates that the everything between [ and m is to be interpreted as a ;-separated list of SGR (Select Graphic Rendition) parameters (See here for more information). The 0 clears all previous text formatting, and the 33 sets the text color to yellow.
myProject
This just adds the string myProject to the bash prompt.
\e[0;32m
This clears all the previous text formatting (0) and sets the text color to green. (32)
\[ ... \]
\[ begins a sequence of non-printing characters which ends with \]. Everything between those two delimiters will not be visible in the prompt.
\e]0;\u#\h: \w\a
This sets the title of the terminal window to something like
username#hostname: /current/working/directory
The next bit:
${debian_chroot:+($debian_chroot)}
If the variable $debian_chroot has been defined, then this expression will evaluate to the value of $debian_chroot.
$debian_chroot is a variable that is set in /etc/bash.bashrc. This post explains it a lot better than I can.
\u#\h:\w\$\e[0m
\u evaluates to the username of the current user, \h evaluates to the name of the computer, and \w evaluates to the current working directory. \$ is just the character $. It needs to be escaped because in bash script, the character $ signifies that the following characters are the name of a variable. \e[0m reverts the text formatting back to default.
An image of what the prompt might look like in a terminal:
This is quite a complicated command you have here!
Let's break it down section by section.
export
This means that we are setting a variable to be used in other programs.
PS1=
The name of the variable is PS1.
\e
This is an escaped character. In bash (and most programming languages), Everything with a backslash before it is an escaped character. It is used for when you need to include a control character like a space, or the control key itself in a string. When it's escaped, bash treats it like it's part of the string, and not another control character.
[
This is the start of an array. It's very similar to an array in a C program.
;
This is an end character, it can mean several different things. Here, it's being used to define part of the array.
There is some other stuff here, but it's mostly just data in the array.
:
This is a NOT operand. It is used to determine the inverse of something.
${debian_chroot:+($debian_chroot)}
This is a variable. In bash, variables start with a $.
It is using the variable debian_chroot and adding it to itself if it's not null.
This command is just defining a variable, in this case an array containing information probably about a chroot with a debian install in it.

Diacritics / Umlauts via Applescript to do shell script

In an Applescript I am trying to pass on a URL that I receive as an argument to a do shell script command to use it with curl.
With regular characters the procedure works fine, but as soon as my argument contains special characters like Umlauts, it gets all funky.
curl does download something, but replaces the letter Ü with à etc., which of course will not get me the correct result.
What do I need to do, to get this to work? I am neither very skilled with Applescript nor with encoding issues.
My setup at the moment is as follows:
set download_URL to item 1 of arguments
do shell script "curl " & download_URL & " > targetFile.html"
Some examples of what happens:
Äquivozität ---> Ãquivozität
Ökolikör ---> Ãkolikör
Übermütigkeit ---> Ãbermütigkeit
Schweißfuß ---> SchweiÃfuÃ
Which makes my confusion even greater. All Ä, Ö, Ü and ß render as Ã, but both in the editing mask here and in the one of the site in question they render as shown in this image.
Also, through some amateurish digging in the html-File, I figured out that instead of the letter Ü, I would need to pass the letters %C3%9C. So the whole procedure does work, if I pass %C3%9Cbermut instead of Übermut. However, I would of course like to avoid creating a translation table for all diacritics.
Can somebody figure out, what specific encoding problem is happening here?
After some more researching, I found out that what I need to urlEncode my string. That way, the letter Ü will be replaced with %C3%9C and it works for my purposes.
Applescript does not seem to support this natively, but one can use php to do the conversion. I found the method here: https://discussions.apple.com/message/9801376#9801376
So, in my case I used it like this:
set keyword to item 1 of arguments
set encodedKeyword to do shell script "php -r 'echo trim(urlencode(" & "\"" & keyword & "" & "\"));'"
do shell script "curl https://www.myUrl.com/" & encodedKeyword & ".html > targetFile"
This way, it works for me.
In case there is a better way - maybe something that works in Applescript directly - feel free to post another answer, then I'll change the accepted answer.

Applescript errors when reading user input (password) that contains escape characters

Here in my department we use a samba shares server as storage space for employees. For the employees that use Apple machines, we are trying to use an AppleScript application that will obtain the users username and password, then using them to mount the drives. The problem arises when a user enters a password that contains escape characters; for example abcdefg/. Here is the dialog code that sets the variables for username and password:
set user_name_dialog to display dialog "Enter your User ID: " default answer "" buttons {"Next"} default button "Next"
set user_name to text returned of user_name_dialog
--this line prompts the user for their password and sets the returned result as the variable "user_password"
set user_password_dialog to display dialog "Enter your Password. " & return & return & "WARNING: If you are running Panther (MacOS 10.3), your input will be displayed in this box as clear text." default answer "" buttons {"Next"} default button "Next" with hidden answer
set user_password to text returned of user_password_dialog
And here is the shell script line that is ran for mounting a drive:
do shell script "mount -t smbfs //" & user_name & ":" & user_password & "#SOME IP ADDRESS/SOME FOLDER/ /SOME MOUNT POINT/" & user_name & "-SOME SHARE"
Now I know from a little research that it could be something as simple as an extra pair of quotes somewhere, I've even tried
quoted form of
with no luck whatsoever. The error message I get when entering a string with a escape character is as such:
error "mount_smbfs: server connection failed: No route to host" number 68
Any help would be GREATLY appreciated as my experience with AppleScript is very limited.
NOTE: the following is just a guess. I did not test any of it.
I don't believe it is an "escape characters" problem. The forward slash is not an escape character. The backward slash is. The problem is probably that the smbfs command interprets the forward slash as a divisor for path variables, and that's causing the error. So the question becomes... how can you avoid the conflict between the forward slash and the smbfs command?
I would try escaping the forward slash when you pass the command to the shell. Note that applescript also uses a backslash as an escape character so to pass an escape character to the shell you will have to escape the escape. So write a custom handler to pass your passwords through to perform that escape process for you.
So if this is your password, "abcdefg/" then try passing it as "abcdefg\\/" (note the double backslash). As mentioned you can write a custom handler to check your password for the "/" character, and if found then insert "\\" in front of it. But before writing that handler try the proposed solution manually to see if it solves your problem.
set pword to "/abc/defg/"
escapeSlash(pword)
on escapeSlash(x)
if x contains "/" then
set AppleScript's text item delimiters to "/"
set textItems to text items of x
set AppleScript's text item delimiters to "\\/"
set x to textItems as text
set AppleScript's text item delimiters to ""
end if
return x
end escapeSlash

Resources