Conditionally add character at end of line

Hi,

I would like have a shell script to check every line in a file to see if it ends with ";". If this is NOT the last character ";" should be added.

MyFile.csv :

web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572
web9331805;01/01/2014 00:00:11;;"877219";352215572
web9331807;01/01/2014 00:00:14;;"624588";352215598

Should be

web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572;
web9331805;01/01/2014 00:00:11;;"877219";352215572;
web9331807;01/01/2014 00:00:14;;"624588";352215598;

Any help ? :slight_smile:

Thanks !

Any attempt from your side?

I would use

sed 's/$/;/' MyFile.csv

to add ; but how do I check this last char for every line ?

Please use code tags as required by forum rules!

Adapting your attempt, try

sed -E 's/(;|.)$/;/' MyFile.csv

EDIT: Don't use - wrong solution!

Thanks !

But I'm getting an invalid option -E ?

Hello vg77,

Welcome to forums, please use code tags for using commands and codes in post as per forum rules. Following may help you in same too.

awk '{$NF=$NF !~ /;$/?$NF=$NF";":$NF} 1' Input_file

Output is as follows.

web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572;
web9331805;01/01/2014 00:00:11;;"877219";352215572;
web9331807;01/01/2014 00:00:14;;"624588";352215598;

Thanks,
R. Singh

I tried Rudis solution without -E and it worked for me (GNU-sed).
Another possible sed-solution:

sed 's/[^;]$/;/' MyFile.csv

EDIT: wrong solution! - do not use!

Try egrep .

@cero: That's removing the last char!

1 Like

@Rudi
thanks for the check - not my day today (didn't get enough sleep)...

RudiC,
When I try:

sed -E 's/(;|.)$/;/' MyFile.csv

it replaces the last character on every line with a semicolon instead of adding a semicolon to the end of lines that don't already have one.

Try:

sed '/[^;]$/s/$/;/' MyFile.csv
3 Likes

Longhand using builtins only, OSX 10.7.5, default shell and terminal...

#!/bin/sh
# add_char.sh
> /tmp/text
> /tmp/txt
echo 'web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572
web9331805;01/01/2014 00:00:11;;"877219";352215572
web9331807;01/01/2014 00:00:14;;"624588";352215598
web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572
web9331805;01/01/2014 00:00:11;;"877219";352215572
web9331807;01/01/2014 00:00:14;;"624588";352215598
web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572
web9331805;01/01/2014 00:00:11;;"877219";352215572
web9331807;01/01/2014 00:00:14;;"624588";352215598
web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572
web9331805;01/01/2014 00:00:11;;"877219";352215572
web9331807;01/01/2014 00:00:14;;"624588";352215598' > /tmp/text
while read line
do
	if [ "${line:$((${#line}-1)):1}" == ";" ]
	then
		printf "$line\n" >> /tmp/txt
	else
		printf "$line"';'"\n" >> /tmp/txt
	fi
done < /tmp/text
cat /tmp/txt

Results...

Last login: Thu Oct 30 19:10:57 on ttys000
AMIGA:barrywalker~> cd ~/Desktop/Code/Shell
AMIGA:barrywalker~/Desktop/Code/Shell> chmod 755 add_char.sh
AMIGA:barrywalker~/Desktop/Code/Shell> ./add_char.sh
web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572;
web9331805;01/01/2014 00:00:11;;"877219";352215572;
web9331807;01/01/2014 00:00:14;;"624588";352215598;
web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572;
web9331805;01/01/2014 00:00:11;;"877219";352215572;
web9331807;01/01/2014 00:00:14;;"624588";352215598;
web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572;
web9331805;01/01/2014 00:00:11;;"877219";352215572;
web9331807;01/01/2014 00:00:14;;"624588";352215598;
web9331801;01/01/2014 23:39:35;;"93962";353150256;
web9331802;01/01/2014 23:44:29;;"479288";353153538;
web9331803;01/01/2014 00:00:11;;"877219";352215572;
web9331805;01/01/2014 00:00:11;;"877219";352215572;
web9331807;01/01/2014 00:00:14;;"624588";352215598;
AMIGA:barrywalker~/Desktop/Code/Shell> _

More variations

sed 's/;\{0,1\}$/;/' file

GNU sed -r / BSD sed -E:

sed -E 's/;?$/;/' file
sed 's/[^;]$/&;/' file

--
For a fixed number of fields:

awk -v n=6 '{$n=x}1' FS=\; OFS=\; file

This happens to work with the supplied sample data (since it does not contain any % or \ characters, but it is very dangerous to use a user-supplied string as a format operand to printf .

This would be much safer:

while read -r line
do	if [ "${line:$((${#line}-1)):1}" == ";" ]
	then	printf '%s\n' "$line"
	else	printf '%s;\n' "$line"
	fi
done < /tmp/text > /tmp/txt

(Note also the addition of the -r option to read .)

1 Like

And here's the inversed corollary of Don Cragun's code...:wink:

sed '/;$/!s/$/;/' file

Another shell version:

while IFS= read -r line
do
  printf "%s\n" "${line%;};"
done < file > newfile
1 Like