I'm trying to make a "sed-replace"-function with arbitrary input as argument, but it doesn't work well. Let me illustrate the problem, first by showing the input file (a simplified file):
$ cat /tmp/makefileTest
#(TEST CASE 1) bla bla line 1, relatively simple:
CFLAGS += -Wunused # this is a comment
#(TEST CASE 2) bla bla line 4, uses some expansion
cp $(OBJ_DIR)/$(EXE_NAME) /tmp/somewhere
#(TEST CASE 3) bla bla line 7, here is a complicated line ending in weird characters:
cd $(SOME_UTIL_BIN); ./somecommand $(BUILD_DIRECTORY_PATH)/$(OBJ_DIR)/\$\^
So I want to apply some custom stuff to this input file (every time I "git pull"), meaning I have a pull-script that checks out a clean copy and then I have a script that should do the necessary modifications, on top of the latest version. The following method below is used on testcase 1 and testcase 2 shown above, the problem however is that it involves a LOT of manual work, hence I call it the "tedious method". I take the input line, modifies and the sed-function should do the necessary replacement(s):
$ cat /tmp/testFunctionTedious.sh
#!/usr/bin/env bash
# The old, tedious method, first defining input-file with test-cases:
inFile='/tmp/makefileTest'
# ----==== TEST-CASE 1 FROM THE INPUT FILE ====----
charsFoundFromGrep=$(grep -in 'CFLAGS += -Wunused # this is a comment' "$inFile" | wc -c)
if [ "$charsFoundFromGrep" = "0" ]; then
echo "Custom makefile modification (CFLAGS += -Wunused # this is a comment) NOT found, doing nothing!"
elif [ "$charsFoundFromGrep" = "41" ]; then
echo "Custom makefile modification (CFLAGS += -Wunused # this is a comment) found and will be applied..."
sed -i 's/CFLAGS += -Wunused # this is a comment/CFLAGS += -Wall # here I changed something/g' "$inFile"
else
echo "ERROR: Unhandled custom makefile modification (CFLAGS += -Wunused # this is a comment), please fix..."
exit 1
fi
# ----==== TEST-CASE 2 FROM THE INPUT FILE ====----
# Notice below that I need to escape $(OBJ_DIR) and $(EXE_NAME), not to
# mention the two forward slashes in the "sed"-line, it's definately not just "plug-and-play":
charsFoundFromGrep=$(grep -in 'cp $(OBJ_DIR)/$(EXE_NAME)' "$inFile" | wc -c)
if [ "$charsFoundFromGrep" = "0" ]; then
echo "Custom makefile modification (cp \$(OBJ_DIR)/\$(EXE_NAME)) NOT found, doing nothing!"
elif [ "$charsFoundFromGrep" = "43" ]; then
echo "Custom makefile modification (cp \$(OBJ_DIR)/\$(EXE_NAME)) found and will be applied..."
sed -i 's/cp \$(OBJ_DIR)\/\$(EXE_NAME)/cp \$(OBJ_DIR)\/\$(EXE_NAME_NEW)/g' "$inFile"
else
echo "ERROR: Unhandled custom makefile modification (cp $(OBJ_DIR)/$(EXE_NAME)), please fix..."
exit 1
fi
I'm trying to learn to make a better/smarter method and learning about bash variable expansion/substitution and handling of special characters. To make things more efficient, I've tried to create the following script and here's where things get too complicated:
$ cat /tmp/testFunction.sh
#!/usr/bin/env bash
# The method I struggle with and ask for help with, first defining input-file with test-cases
inFile='/tmp/makefileTest'
# *** Defining a sedReplace-function below ***
# First arg: Search (input) string
# Second arg: Replacement (output) string
# Third arg: Expected number of characters using 'grep -in "$1" "$inFile" | wc -c)',
# this is just to ensure the line I'm going to run sed on didn't change, otherwise
# output and error involving the input message (hence the string comparison that
# relates argument 3 with grep from argument 1 (the input string).
sedReplace(){
# sed -i 's/$1/$2/g' "$inFile"
charsFoundFromGrep=$(grep -in "$1" "$inFile" | wc -c)
if [ "$3" == "$charsFoundFromGrep" ]; then
# Getting the line below right is REALLY difficult for me!
execLine="sed -i 's/$1/$2/g' \"$inFile\""
# Printing the line, so I can see it before executing the line:
echo "$execLine"
# Executing the line if ok (disabled as it doesn't work at the moment):
#$($execLine)
else
echo "ERROR: Unhandled custom makefile modification (expected: $1)), please fix..."
exit 1
fi
}
# And below the function is used (1st arg is input, 2nd arg is sed-
# output and 3rd arg is grep comparison word count):
# ----==== TEST-CASE 1 FROM THE INPUT FILE ====----
sedReplace 'CFLAGS += -Wunused # this is a comment' 'CFLAGS += -Wall # here I changed something' 41
# ----==== TEST-CASE 2 FROM THE INPUT FILE ====----
#sedReplace 'cp $(OBJ_DIR)/$(EXE_NAME)' 'cp $(OBJ_DIR)/$(EXE_NAME_NEW)' 43
# ----==== TEST-CASE 3 FROM THE INPUT FILE ====----
# Once the above 2 cases work, here's the last test-case to try the sedReplace function on (the hardest, I imagine):
# And here grep don't work, due to the special characters
#sedReplace 'cd $(SOME_UTIL_BIN); ./somecommand $(BUILD_DIRECTORY_PATH)/$(OBJ_DIR)/\$\^' 'cd $(SOME_UTIL_BIN); ./someOTHERcommand $(BUILD_DIRECTORY_SOMETHING_ELSE)/$(OBJ_DIR)/\$\^'
You'll easily see that the last script doesn't work. I've tried to google and lot about similar problems, but can't find it. I don't know how to finish my sed-function. That's what I'm asking about help for. Qualified and interested people should be able to run the scripts and input-file exactly as shown here and I look forward to see if anyone can solve the problem.
"$s3"
be"$3"
? – schrodingerscatcuriosity Nov 19 '19 at 17:43shellceheck
and it will tell you things such as to double quote"$1"
and"$2"
– WinEunuuchs2Unix Nov 19 '19 at 23:06