8

I'd like to perform a series of sed commands on lines of a file roster.txt only beginning with a keyword. For example:

Employee : Kiara 20 hours@8.25
Employee : Connor 25 hours@8.00
Employee : Dylan 30 hours@9.00

Becomes:

Employee : Kiara_20_hoursat8dot25
Employee : Connor_25_hoursat8dot00
Employee : Dylan_30_hoursat9dot00

I know the sed commands to make the changes I just wanted a way to peform them on lines starting with "employee". Maybe

awk '$1 == "Employee" {sed -i -e 's/\./dot/g' roster.txt}' roster.txt
cbrad97
  • 83
  • 1
  • 1
  • 5

3 Answers3

9
$ cat roster.txt
foo : bar@baz.123
Employee : Kiara 20 hours@8.25
Employee : Connor 25 hours@8.00
Employee : Dylan 30 hours@9.00

$ awk 'BEGIN{FS=OFS=" : "} $1=="Employee"{gsub(/ /,"_",$2); gsub(/@/,"at",$2); gsub(/\./,"dot",$2)} 1' roster.txt
foo : bar@baz.123
Employee : Kiara_20_hoursat8dot25
Employee : Connor_25_hoursat8dot00
Employee : Dylan_30_hoursat9dot00

awk supports substitution commands as well - sub to replace first occurrence and gsub to replace all occurrences. Also allows to change only specific field

  • BEGIN{FS=OFS=" : "} use : as input/output field separator
  • gsub(/ /,"_",$2) replace all spaces with _ only for second field
  • Similarly other substitutions as required
  • 1 at end of command is idiomatic way to print the line, includes any changes made
  • See also awk save modifications in place
Sundeep
  • 23,246
  • 2
  • 28
  • 103
  • will this write to the original file? – cbrad97 Aug 08 '17 at 15:38
  • @cbrad97 see https://stackoverflow.com/questions/16529716/awk-save-modifications-in-place – Sundeep Aug 08 '17 at 15:54
  • so if i dont have GAWK 4.1 or later, i need to create a temp file to write to? I kind of need the original name of the file to be intact – cbrad97 Aug 08 '17 at 18:27
  • @cbrad97 the second answer there suggests the way to do it... `awk ... roster.txt > tmp && mv tmp roster.txt`... the `-i inplace` option with gawk does the same – Sundeep Aug 09 '17 at 01:28
2

I'd write:

sed '/^Employee :/ {s/@/at/; s/\./dot/; s/ /_/3g}' <<END
Employee : Kiara 20 hours@8.25
Employee : Connor 25 hours@8.00
Employee : Dylan 30 hours@9.00
Foo : bar baz@qux.blah
END
Employee : Kiara_20_hoursat8dot25
Employee : Connor_25_hoursat8dot00
Employee : Dylan_30_hoursat9dot00
Foo : bar baz@qux.blah

Requires GNU sed for the 3g modifier of the s command

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • good one, though I'd have used `!b` see https://www.gnu.org/software/sed/manual/sed.html#Programming-Commands – Sundeep Aug 08 '17 at 16:09
  • Does next record mean next file or next line in the current file? When i run the command, !n is replaced with another filename? – cbrad97 Aug 08 '17 at 19:16
  • I think that's bash doing [history expansion](https://www.gnu.org/software/bash/manual/bashref.html#History-Interaction), where `!n` is your previous command that begins with "n". Try turning hist expansion off with `set +H` (turn it on after with `set -H`) – glenn jackman Aug 08 '17 at 21:00
  • @glennjackman in fact it has to be `!b` not `!n`, for example try two consecutive lines not starting with `Employee`... and history expansion won't come into picture inside single quotes – Sundeep Aug 09 '17 at 01:30
0

You really do not need to use both tools, either will do everything you need.

sed solution:

 sed -i -e 's/^Employee : \([^ ]*\) \([0-9]*\) hours@\([0-9]\)\.\([0-9]*\)/Employee : \1_\2_hoursat\3dot\4/' roster.txt

Edit after comment:

If you want a very generic replacement using only sed that works on your sample:

sed -i -e 's/\([^:]\) \([^:]\)/\1_\2/g' -e 's/@/at/g' -e 's/\./dot/g' roster.txt
Rob
  • 2,618
  • 2
  • 22
  • 29
  • What if i dont know the fields following the colon? I just know that I have a series of sed substitutions to perform on any text following the colon. – cbrad97 Aug 08 '17 at 14:52
  • make the pattern more generic. You want to the and keep the patter as restrictive as possible while still capturing all your case the last thing you want is for a substitution to occur that you did not intend. I will add another option that will work on the sample but could be riskier. – Rob Aug 08 '17 at 14:57