1

I have a csv file, with student name and marks. I want to update "marks" of a student with name "jack"(the only person in the csv). the data in csv file looks as below.

student,marks jack,10 peter,20 rick,10 

I found this awk '$1 == "Audrey" {print $2}' numbers.txt, but iam not sure on how to modify the file.

3
  • The traditional (and most correct) approach is: awk ... numbers.txt > output && mv output numbers.txt or similar. Commented Mar 17, 2020 at 21:11
  • I would use sed: sed -i 's/jack,.*/jack,12/g' numbers.txt where 12 is the new mark Commented Mar 17, 2020 at 21:18
  • Thank you Andres, but i get the error sed: 1: "input.csv": command i expects \ followed by tex Commented Mar 17, 2020 at 21:26

5 Answers 5

3
awk 'BEGIN{FS=OFS=","} $1=="jack"{$2=27} 1' foo.csv > tmp && mv tmp foo.csv 
Sign up to request clarification or add additional context in comments.

Comments

1

It worked for me with

sed -ir "s/^\(jack\),.*/\1,$new_grade/" 

input.csv. with argument "r" or else i get the "error sed: 1: "input.csv": command i expects \ followed by text".

1 Comment

Your version of sed apparently requires -i to take an argument. Just use awk.
1

ed is usually better for in-place editing of files than sed:

printf "%s\n" "/^jack,/c" "jack,${new_grade}" "." w | ed -s input.csv 

or using a heredoc to make it easier to read:

ed -s input.csv <<EOF /^jack,/c jack,${new_grade} . w EOF 

At the first line starting with jack,, change it to jack,XX where XX is the value of the new_grade variable, and write the new contents of the file.

Comments

0

You could use sed:

new_grade=9 sed -i'' "s/^\(jack\),.*/\1,$new_grade/" 

The pattern ^\(jack\),.* matches the beginning of the line ^ followed by jack by a comma and the rest of the line .*. The replacement string \1,$new_mark contains the first captured group \1 (in this case jack) followed by a comma and the new mark.

Alternatively you could loop over the file and use a pattern substitution:

new_grade=9 while read -s line; do echo ${line/jack,*/jack,$new_grade} done < grades.txt > grades2.txt 

2 Comments

thank you @Serigo can this be done using a bash script? or awk?
but this command should update my csv file, this just prints the updated file?
0

Another approach with sed is to anchor the replacement to the digits at the end of the line with:

sed '/^jack,/s/[0-9][0-9]*$/12/' file 

This uses the form sed '/find/s/match/replace' where find locates at the beginning of the line '^' the word "jack," eliminating all ambiguity with, e.g. jackson,33. Then the normal substitution form of 's/match/replace/' where match locates at least one digit at the end of the line (anchored by '$') and replaces it with the 12 (or whatever you choose).

Example Use/Output

With your example file in file, you would have:

$ sed '/^jack,/s/[0-9][0-9]*$/12/' file student,marks jack,12 peter,20 rick,10 

(note: the POSIX character class of [[:digit:]] is equivalent to [0-9] which is another alternative)

The equivalent expression using the POSIX character class would be:

sed '/^jack,/s/[[:digit:]][[:digit:]]*$/12/' file 

You can also use Extended Regular Expression which provides the '+' repetition operator to indicate one-or-more compared to the basic repetition designator of '*' to indicate zero-or-more. The equivalent ERE would be sed -E '/^jack,/s/[0-9]+$/12/' file

You can add the -i option to edit in-place and/or using it as -i.bak to create a backup of the original with the .bak extension before modifying the original.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.