parameter expansion syntax bash - bash

I am trying to write a short script that will take two command line parameters as file extensions and change all files with the first extension to have the second extension. I am pretty sure the following script should work but for some reason it gives me a syntax error on the line where the variable name is defined and I am not sure why. I am rather new to bash scripting so any help would be greatly appreciated!
for f in "*$1" do
name=${f%.*}
mv $f "$name$2"
done
The error message printed by Bash looks like:
./script: line 4: syntax error near unexpected token `name=${f%.*}'
./script: line 4: `name=${f%.*}'

The reason is that you are missing a ; or newline before do. Also you don't want to quote * in "*$1", since the * will be taken as a literal. Corrected script:
#!/usr/bin/env bash
for f in *"$1"; do
name=${f%.*}
mv "$f" "$name$2"
done

Related

How to see syntax errors reported with actual line numbers in the parent script when Perl is embedded within shell script?

For no justifiable reason at all, I have a pretty substantial Perl script embedded within a Bash function that is being invoked within an autoenv .env file.
It looks something like this:
perl='
$inverse = "\e[7m";
$invoff = "\e[27m";
$bold = "\e[1m";
⋮
'
perl -e "$perl" "$inputfile"
I understand that standalone Perl scripts and the PATH variable are a thing, and I understand that Term::ANSIColor is a thing. This is not about that.
My question is, if there's a syntax error in the embedded Perl code, how can I get Perl to report the actual line number within the parent shell script?
For example, say the perl= assignment occurs on line 120 within that file, but there's a syntax error on the 65th line of actual Perl code. I get this:
syntax error at -e line 65, near "s/(#.*)$/$comment\1$endcomment/"
Execution of -e aborted due to compilation errors.
…but I want to see this (the actual line number in the parent script) instead:
syntax error at -e line 185, near "s/(#.*)$/$comment\1$endcomment/"
Things I've tried (that didn't work):
assigning to __LINE__
don't even know why I thought that would work; it's not a variable, it's a constant, and you get an error stating the same
assigning to $. ($INPUT_LINE_NUMBER with use English)
I was pretty sure this wasn't going to work anyway, because this is like NR in Awk, and this clearly isn't what this is for
As described in perlsyn, you can use the following directive to set the line number and (optionally) the file name of the subsequent line:
#line 42 "file.pl"
This means that you could use
#!/bin/sh
perl="#line 4 \"$0\""'
warn("test");
'
perl -e "$perl"
Output:
$ ./a.sh
test at ./a.sh line 4.
There's no clean way to avoid hardcoding the line number when using sh, but it is possible.
#!/bin/sh
script_start=$( perl -ne'if (/^perl=/) { print $.+1; last }' -- "$0" )
perl="#line $script_start \"$0\""'
warn("test");
'
perl -e "$perl"
On the other hand, bash provides the current line number.
#!/bin/bash
script_start=$(( LINENO + 2 ))
perl="#line $script_start \"$0\""'
warn("test");
'
perl -e "$perl"
There is this useful tidbit in the perlrun man page, under the section for -x, which "tells Perl that the program is embedded in a larger chunk of unrelated text, such as in a mail message."
All references to line numbers by the program (warnings, errors, ...) will treat the #! line as the first line. Thus a warning on the 2nd line of the program, which is on the 100th line in the file will be reported as line 2, not as line 100. This can be overridden by using the #line directive. (See Plain Old Comments (Not!) in perlsyn)
Based on the bolded statement, adding #line NNN (where NNN is the actual line number of the parent script where that directive appears) achieves the desired effect:
perl='#line 120
$inverse = "\e[7m";
$invoff = "\e[27m";
$bold = "\e[1m";
⋮
'
⋮

Error in BASH shell script - Using Variables as References

Two questions about problems I'm having writing up a BASH script that uses variables. I cannot for the life of me figure this out and it is KILLING me.
1) I have the following code.
pdir=/media/The_Enforcer/ICA_Doug/Participants/RS1
cd ${pdir}
for subject in * ; do
subdir=${pdir}/${subject} ;
cd ${subdir} ;
subj= echo ${subject} | head -c-9
3dAFNItoNIFTI -prefix ICA/cleanRS_NII_${subj} RSFC_LFF_rall_${subj}+orig ;
cd ${pdir} ;
done
${subject} is a subject ID which is ########.results. For example: 1R101U1A.results. Basically my code cd's me into that directory in which is a file called RSFC_LFF_rall_1R101U1A+orig which I want to process via the code line that starts with 3dAFNItoNIFTI. Obviously I can't use ${subject} variable in that code line because it would attempt to find the file RSFC_LFF_rall_1R101U1A.results+orig which does not exist. So to fix this I made a new variable called ${subj} which, via the echo pipeline, basically cuts off the last 9 letters of ${subject} which, in effect, removes the .results. When I do this and echo ${subj} it gives me 1R101U1A which is exactly what I want.
However, the line of code that starts with 3dAFNItoNIFTI errors with the following:
FATAL ERROR: Can't open dataset 'RSFC_LFF_rall_+orig'
I have tried declaring the ${subj} variable like, five different ways (including using head, tail, cut, and colons) and I still get this error.
What am I doing wrong?
2) In attempting to define ${subj} in numerous ways I also tried this method:
${subj}= ${subject:0:8}
When I did this, the final bracket refused to close - i.e. the closing bracket did not turn the color of the opening bracket and when I attempted to run the script I got an error at that line saying 'command not found.' I checked my syntax against the examples I was following and it looks fine? Am I missing something here?
Try this:
cd "/media/The_Enforcer/ICA_Doug/Participants/RS1"
for subject in * ; do
cd $subject
subj=${subject%.results}
3dAFNItoNIFTI -prefix ICA/cleanRS_NII_${subj} RSFC_LFF_rall_${subj}+orig
cd ..
done
${subject%.results} removes .results from the end of the string.
See Shell-Parameter-Expansion.

INI file parsing with KSH

I found this bash script here on stackoverflow that parses an ini file with bash, and it works great. But I'd like to convert this to ksh but get this message when running it with ksh...
ini_test02.ksh[24]: eval: syntax error at line 7: `end of file' unexpected
ini_test02.ksh[51]: cfg.section.DEFAULT: not found [No such file or directory]
How can you convert this into a ksh script?
If you do not have a lot of vars, just parse them one by one. When the values do not contain an equal sign the following might do:
keyx="$(grep "^keyx=" my.ini | cut -d= -f2 | sed 's/ *$//')"
Or put this in a function and call the function like
keyx="$(readini my.ini keyx)"
Since this is one of the top search results on google with ksh and INI parsing I'd like to point to https://github.com/wallyhall/shini for INI parsing in KSH.
The only thing that needs to be done is to implement the function(s) __shini_parsed and optional __shini_parsed_section.

-bash: syntax error near unexpected token `)'

I'm probably missing something very basic. I have a web script that tells a shell script to update some database records. These records are for statistics, and this way the web script does not have to wait while the database records are updated. However, I can't actually make the shell script work running it from commandline. Here is the code that I'm trying:
perl async_sql.pl 'UPDATE some_table set i = i + 1 WHERE (n in (\'328430\',\'334969\',\'330179\',\'335290\',\'335285\',\'335284\',\'335264\',\'335145\',\'335146\',\'335147\',\'335148\',\'335149\',\'335230\',\'335201\',\'335198\',\'335196\',\'335167\',\'335151\',\'335152\',\'335143\',\'334969\',\'334972\',\'334977\',\'334978\',\'334979\',\'334980\',\'334982\',\'334983\',\'334984\',\'334934\',\'334947\',\'334948\',\'334950\',\'334992\',\'335014\',\'335026\',\'335030\',\'335032\',\'334864\',\'334862\',\'334861\',\'334858\',\'334855\',\'334852\',\'334850\',\'334849\',\'334848\',\'334847\',\'334844\',\'334842\'))'
Bash tells me:
-bash: syntax error near unexpected token `)'
What am I missing?
It is not possible to escape single quote in single quotes. Use " " instead
perl async_sql.pl "UPDATE some_table set i = i + 1 WHERE (n in ('328430','334969','330179','335290','335285','335284','335264','335145','335146','335147','335148','335149','335230','335201','335198','335196','335167','335151','335152','335143','334969','334972','334977','334978','334979','334980','334982','334983','334984','334934','334947','334948','334950','334992','335014','335026','335030','335032','334864','334862','334861','334858','334855','334852','334850','334849','334848','334847','334844','334842'))"
Also, there are other ways to deal with this problem:
echo "quote'test"
echo 'quote'"'"'test'
echo 'quote'\''test'
echo $'quote\'test'
All these should print quote'test as a single parameter. Which means that another great solution for your problem is:
perl async_sql.pl $'UPDATE some_table set i = i + 1 WHERE (n in (\'328430\',\'334969\',\'330179\',\'335290\',\'335285\',\'335284\',\'335264\',\'335145\',\'335146\',\'335147\',\'335148\',\'335149\',\'335230\',\'335201\',\'335198\',\'335196\',\'335167\',\'335151\',\'335152\',\'335143\',\'334969\',\'334972\',\'334977\',\'334978\',\'334979\',\'334980\',\'334982\',\'334983\',\'334984\',\'334934\',\'334947\',\'334948\',\'334950\',\'334992\',\'335014\',\'335026\',\'335030\',\'335032\',\'334864\',\'334862\',\'334861\',\'334858\',\'334855\',\'334852\',\'334850\',\'334849\',\'334848\',\'334847\',\'334844\',\'334842\'))'
I have only placed a dollar sign $ right before the parameter. That's it. A dollar sign before single quotes turns on ANSI-C Quoting
bash: syntax error near unexpected token `('
this type of error can be solve by the turn on extended globbing by git bash command is "shopt -s extglob"

syntax error near unexpected token `

The following script is intended to run the program "senna" on all files in a directory and write the output for each file (preserving the input file name) into another directory
for file in ./Data/in/*;
do
./senna -iobtags -usrtokens -posvbs -srl < $file > ./Data/out/$file
done
On trying to execute the script, the following error arises.
-bash-4.0$ sh run.s
'un.s: line 1: syntax error near unexpected token `
'un.s: line 1: `for file in ./Data/in/*;
The script has the lines of code exactly as above and there is no `. Perhaps it implies something else. Help with error resolution would be appreciated.
The line endings in the script are wrong. Pass it through dos2unix to eliminate the CRs.

Resources