Reputation: 15
could anyone tell me why this is happening? im trying to insert some lines before an occurrence of a given string, say...
thing
extern void hello_dude(char *loc, long length){
thing
to
thing
another
extern void hello_dude(char *loc, long length){
thing
with a simple (sigh) bash 3.0 script, the thing is that the if statement im using to match the string is echoing the line splitted like this:
thing
another
extern
void
hello_dude(char
*loc,
long
length){
thing
the statement is
elif [[ "$LINE" =~ *hello_dude\(* ]]; then
echo "$LINE" >> temp2
theres obviously a leading if statement working OK before the elif.
Ive tried every quote flavor and regex i can imagine...
any help will be much appreciated
EDIT: this is the actual script im using
#!/bin/bash
for LINE in `(cat temp1)`
do
if [[ "$LINE" = sendMessage4K* ]]; then
echo '/*---RUAISI---*/' >> temp2
echo "$LINE" >> temp2
elif [[ "$LINE" =~ *alpha_display\(* ]]; then
echo "$LINE" >> temp2
echo '/*---RUAISI---*/' >> temp2
else
echo "$LINE" >> temp2
fi
done
the temp1 file is:
FIX
sendMessage4K(NomRPC,sbuffer,"KP07");
FIX
extern void alpha_display(char *loc, long length){
FIX
}
FIX
the idea is to get temp2 with:
FIX
/*---RUAISI---*/
sendMessage4K(NomRPC,sbuffer,"KP07");
FIX
extern void alpha_display(char *loc, long length){
/*---RUAISI---*/
FIX
}
FIX
but im getting this
FIX
/*---RUAISI---*/
sendMessage4K(NomRPC,sbuffer,"KP07");
FIX
extern
void
alpha_display(char
/*---RUAISI---*/
*loc,
long
length){
FIX
}
FIX
Upvotes: 0
Views: 208
Reputation: 311635
EDIT: Whoops, my answer mostly duplicates the one from choroba. I'm going to leave it here because I think it goes into a little more detail about the why of things, but you should probably accept choroba's.
Your problem is here:
for LINE in `(cat temp1)`
This splits up each line use IFS
, so that given an input line like this:
extern void alpha_display
You get a for loop that looks something like this:
for LINE in extern void alpha_display; do
Which means that LINE
is set to, in sequence:
To demonstrate this, try the following little script:
for LINE in `cat temp1`; do
echo "$LINE"
done
If you really want to read a file line-by-line, you're better off using read
in a while
loop with input redirected from your souce file. Compare the output of the following to what the previous script produces:
while read LINE; do
echo "$LINE"
done < temp1
With this in mind, you can fix your script like this:
while read LINE; do
if [[ "$LINE" = sendMessage4K* ]]; then
echo '/*---RUAISI---*/' >> temp2
elif [[ "$LINE" = *alpha_display\(* ]]; then
echo '/*---RUAISI---*/' >> temp2
fi
echo "$LINE" >> temp2
done < temp1
Notice that in addition to using a while
loop, I've also removed the regular expression operator from the elif
expression (because, as has previously been pointed out, you were using glob expressions rather than regular expressions), and I've eliminated some redunant code.
This script produces the following output:
FIX
/*---RUAISI---*/
sendMessage4K(NomRPC,sbuffer,"KP07");
FIX
extern void alpha_display(char *loc, long length){
/*---RUAISI---*/
FIX
}
FIX
Because read
is in fact still splitting things on IFS (and then putting them back together), you end up losing leading or trailing whitespace. You can fix this by making IFS include only end-of-line by adding the following to the top of the script:
IFS='\n'
I would still suggest that bash
isn't necessarily the right tool for this job. Either sed
or awk
is probably going to be more effective. Here's the same thing as an awk script:
#!/usr/bin/awk
/sendMessage4K/ || /alpha_display\(/ {
print "/*---RUAISI---*/"
print
next
}
{print}
If you saved this in a file named "fixit.awk", you would run it like this:
awk -f fixit.awk < temp1 > temp2
Upvotes: 1
Reputation: 241898
You are using the regular expression matching operator =~, but on the right hand side of it, there is no regular expression, but a shell wildcard expression. So, change it to
[[ $LINE == *hello_dude\(* ]]
or
[[ $LINE =~ hello_dude\( ]]
i.e. use either wildcard with the proper operator, or a regex with the proper operator.
Update: Looking at the updated script, I see the problem: you are using for
where you should be using while
:
#! /bin/bash
while read LINE ; do
if [[ $LINE = sendMessage4K* ]]; then
echo '/*---RUAISI---*/' >> temp2
echo "$LINE" >> temp2
elif [[ $LINE =~ *alpha_display\(* ]]; then
echo "$LINE" >> temp2
echo '/*---RUAISI---*/' >> temp2
else
echo "$LINE" >> temp2
fi
done < temp1
To avoid deletion of leading whitespace, add this line before the while
:
IFS=$'\n'
Upvotes: 1
Reputation: 311635
Without seeing your script we can't really help you with that. However, this sort of problem -- inserting a line of text before a particular matching pattern -- is often handled using sed
. For example, if I have a file that looks like this:
one
two
three
And I want to insert "Bananas" before "two", I would do something like this:
sed '/two/ i\Bananas'
Which gives me:
one
Bananas
two
three
This assumes GNU sed
(although it would work with minor modifications for other versions of sed, also).
Upvotes: 0