Add character to specific columns using sed or awk and make it a permanent change

Hi,

I am writing a shell script where I want that # should be added in all those lines as the first character where the pattern matches.

file has lot of functions defined
a.sh

#!/bin/bash

 fn a {
beautiful evening
sunny day
}
fn b {
}

fn c {
 hello world .its a beautiful day
 my mom is beautiful.
 my doll is beautiful
 all things bright and beautiful
 all creatures great and small
}

so when i execute the command on a.sh, the file should only be modified for places that has beautiful word

so the new file should be
a.sh

#!/bin/bash

 fn a {
# beautiful evening
sunny day
}
fn b {

}

fn c {
# hello world .its a beautiful day
# my mom is beautiful.
# my doll is beautiful
# all things bright and beautiful
 all creatures great and small
}

command i could create was

cat a.sh | grep -i "beautiful" | awk -F" " '{$1="#" $1;}1' OFS=" "

but it doesnt modify in the file. It only gives op on comd prompt. I dont want to create a new file. I want it modified in original file

Please use code tags as required by forum rules!

Try

awk '/beautiful/ {printf "#"} 1' file > tmp$$; mv tmp$$ file 

search these forums for "in place file replacement".

1 Like

Sorry new to unix.com. Didnt explore much.
Thanks!!! It resolved the issue.
Can you explain temp$$?

Hello ashima,

You are most welcome to forum, hope you will enjoy learning here. echo $$ will be used to write PID of the current shell.
So tmp$$ is just a Temporary file created in above code, which is later renamed to actual file. Complete explanation is as follows.

 
awk '/beautiful/  #### Searching for string beautiful here.
{printf "#"}      #### If above condition is TRUE then printing string #
1'                #### awk works on pattern of condition and action/operation so if we give condition here 1 which means we are making condition TRUE so default action will be happening here which is print for awk.
file > tmp$$;     #### mentioning Input_file named file here as putting output into file named tmp with $$ shell's pid.
mv tmp$$ file     #### renaming tmp$$ file to actual Input_file which is file.
 

Thanks,
R. Singh

1 Like

You could also try ed or ex with any shell that has a syntax based on the Bourne shell (e.g., ash, bash, ksh, zsh...):

#!/bin/ksh
ed -s a.sh <<-EOF
	g/beautiful/s/^/#/
	w
	q
EOF

These utilities might use a temp file internally, but you won't need to create one on your own this way.

1 Like
sed -n 'p; /{/{ :L n; /}/p; s/\(.*\)/#\1/p; bL; };n;p;' file6
#!/bin/bash

 fn a {
# beautiful evening
# added
# sunny day
 }
# }
# fn b {
 }
# }
#
# fn c {
#  hello world .its a beautiful day
#  my mom is beautiful.
#  my doll is beautiful
#  all things bright and beautiful
#  all creatures great and small
 }
# }

I have tried branching

/}/p;

with

{/}/{p; bL;}}

I just get an error. I have branched successfully with L but can't seem to be able inside another Curly set.
I know I don't yet have the correct output for # on last line of curly set, right now I just want to understand the branching stuff, then I will try to fix the other problem after.
Thanks

Not sure what you want to achieve. Your script prefixes almost - not all - lines with a # , except when an opening brace is encoutered. That could be done more easily with e.g. sed '/{/ !s/^/#/' file

n;p; doesn't mean a thing; if you drop it, sed will automatically read a new line and print it.
You don't match the pattern (beautiful) which is required.

I know this doesn't work, my question is how to do the, if not, THEN in sed? I guess I use the branching but had less than success with it, anyway let me know.

sed -n 'p;/{/ !s/^/#/; s/^\(.*\)/# \1/' file6

If not

{

then add

# 

with the other sustitute statement. Thanks

P.S. Simply put, If I am too confusing maybe show me how to do this particular example with sed, the original question.

That is not the original question. The original question was how to put an octothorps at the start of every line that contains the string beautiful . The obvious way to do that in sed is:

sed '/beautiful/s/^/#/' file

but the original request was also to put the results back in the input file. Just using standard sed features (i.e., no -i option), that can be done with:

sed '/beautiful/s/^/#/' file > file.$$ && cp file.$$ file;rm -f file.$$

But, if you did want to add an octothorpe to the lines that do NOT contain beautiful, you can do that in sed with:

sed '/beautiful/n;s/^/#/' file

Sorry Don will ask the question as a new one,
thanks

while read line
do
   echo "$line" |grep beautiful >/dev/null 2>&1
   if [ $? = 0 ]
   then
     echo "#$line"
   else
     echo "$line"
   fi
done <a.sh

If you want to write it using a script.

Rudic can you explain !s
sed '/{/ !s/^/#/' file

From the standards:

Or, translated from standardese, perform the specified substitution (insert an octothorpe at the start of a line) on lines that do not contain an open brace character.

1 Like