I am trying to use a shell script file in the Bash shell. In this script, 2 sed commands are there. The second sed command is following.
sed -e s:MACRO_NAME:"${runmacro}":g \ -e s:INFILE_PATH_NAME:"${filedir}"/"${filename}":g \ -e s:INFILE_NAME:"${filename%.*}":g \ -e s:INDEX:"${index}":g \ -e s:TREE_NAME:"${treename}":g \ -e s:SUFFIX:"${suffix}":g \ -e s:SMEAR_TEMPLATE_NAME:"${smeartemplatename}":g \ -e s:IS_MC:"${ismc}":g \ -e s:PWD:.:g \ -e s:SCRAM_DIR:"${scramdir}":g \ -e s:OUTFILE_NAME:"${outfilename}":g \ -e s:OUTFILE_DIR:"${outputpath}":g \ -e s:PREFIX:"${prefix}":g \ -e s:OUTPUT_DIR:"${outputdir}":g \ template_files/submit_script_template.sh > tempfile \
&& mv tempfile ../"${outputdir}"/submit_"${outputdir}"_"${index}".shBy executing the .sh file, I am getting this error:
sed: -e expression #2, char 25: unknown option to `s'I added echo to sed also. The result is:
sed -e s:MACRO_NAME:QCDSmearedSkimmer.C:g \ -e s:INFILE_PATH_NAME:root:// \ -e s:INFILE_NAME:qcd_ht1000to1500-ext_10_ntuple_postproc:g \ -e s:INDEX:2:g \ -e s:TREE_NAME:Events:g \ -e s:SUFFIX:SmearedQCD:g \ -e s:SMEAR_TEMPLATE_NAME:resTailOut_combined_filtered_CHEF_puWeight_weight_WoH.root:g \ -e s:IS_MC:1:g \ -e s:PWD:.:g \ -e s:SCRAM_DIR:${CMSSW_BASE}:g \ -e s:OUTFILE_NAME:qcd_ht1000to1500-ext_10_ntuple_postproc_1_SmearedQCD.root:g \ -e s:OUTFILE_DIR:/ddash/nobackup/mywork/qcd/CMSSW_9_4_6_patch1/src/AnalysisMethods/macros/Skims/generate_smear_scripts/smeared_file/:g \ -e s:PREFIX:root:// \ -e s:OUTPUT_DIR:qcd_smeared_file3:g \ template_files/submit_script_template.sh > tempfile \
&& mv tempfile ../qcd_smeared_file3/submit_qcd_smeared_file3_2.shPlease help me to fix this problem.
72 Answers
In the sed expression s:INFILE_PATH_NAME:"${filedir}"/"${filename}":g, there are five parts:
- the
sedcommands, - the search pattern for that command (
INFILE_PATH_NAME), - the replacement text (whatever
"${filedir}"/"${filename}"- in this example, that'sroot://), - options to the
scommand (hereg), - and the delimiter that separates all these, which is
:(colon) here.
Now, if the replacement text contains :, then sed will think that the replacement text ends there, and whatever follows are options to s. So instead of
- replacement:
root:// - option:
g,
we get:
- replacement:
root - option:
//
which is invalid as far as sed is concerned.
Suggested solutions:
use a different delimiter, some character which won't appear in the replacement text, such as
,(comma),;(semicolon), etc. For example:sed -e "s,INFILE_PATH_NAME,${filedir}/${filename},g" ...- Wherever you get your input from, escape
:with a backslash so that it becomes\:.
The error appears because your variables (at least some of them) contain colons (:) and you use a colon as the delimiter for the s/…/…/ command. Actually for the s:…:…: command in your case.
When you have
var="ex:ample"and then try to issue
sed -e "s:${var}:sample:g" some_filethen the shell interpolates the variable before handing it over to sed, and sed is called like so:
sed -e "s:ex:ample:sample:g" some_fileand the s:…:…: is now broken. It looks like you are telling sed to replace ex with ample and apply the options s, a, m, p, l, and e.
To avoid this, use a different delimiter which you are sure of it doesn't appear in your text. Popular delimiters are + and # but you can choose any character. The delimiter is in fact the first character after the s, so
sed -e "s#…#…#" some_file
sed -e "s+…+…+" some_file
sed -e "s'…'…'" some_filewill all do.
1