Zach
Zach

Reputation: 148

Modify non-unique line in file with sed/awk

I want to replace a line in a file using bash tools like sed or awk. The part that makes this hard is that the line is not unique, so how can I match it?

I'm sure getting the match by itself could be done other ways, but I only know the following command for replacing lines:

sed -i "s,^    AGE: .*,    AGE: ${age}," profiles.txt

The profiles.txt looks like:

ALICE:
    AGE: 
    GRADE: 
BOB:
    GRADE: 
    AGE: 
...

How can I find the AGE: line for a specific person and update it? The fields for each person can be in any order, and so can the people. The people will always have both fields, they're just blank if unknown.

Upvotes: 0

Views: 134

Answers (3)

Paul Hodges
Paul Hodges

Reputation: 15313

A simplistic sed script:

#! /bin/bash

declare -u student=$1
declare -u key=$2
declare    val=$3

sed -Ei "/^$student:/,/^\S/{ s/$key:.*/$key: $val/; }" profiles.txt

Executed:

$: cat profiles.txt
ALICE:
    AGE:
    GRADE:
BOB:
    GRADE:
    AGE:

$: update alice grade 70

$: cat profiles.txt
ALICE:
    AGE:
    GRADE: 70
BOB:
    GRADE:
    AGE:

declare -u automatically uppercases the string assigned to the variable. This was a pretty simple pattern set, so I was able to just use double-quotes.


addendum

this works fine on the last block:

$: update bob age 14
$: cat profiles.txt
ALICE:
    AGE:
    GRADE: 70
BOB:
    GRADE:
    AGE: 14

The toggle is still on at the end of the file because nothing turns it off, but that is functionally ok. :)

Upvotes: 1

anubhava
anubhava

Reputation: 785286

You may use this awk (assuming you want to change AGE for person BOB):

awk -v age=20 -v name='BOB' '/^[[:alpha:]]+:/ {
   p = ($0 ~ "^" name ":")
}
p && /^[[:blank:]]+AGE:/ {
   sub(/AGE:.*/, "AGE: " age)
} 1' file.yml

ALICE:
    AGE:
    GRADE:
BOB:
    GRADE:
    AGE: 20

Upvotes: 4

Jotne
Jotne

Reputation: 41454

You can do it like this in awk to set the age for BOB

age=10
awk -v val=${age} '/BOB/ {f=1} f && /AGE/ {$0=$0 FS val;f=0} 1' file
ALICE:
    AGE:
    GRADE:
BOB:
    GRADE:
    AGE:  10
...

It will find BOB and set f to true. The if f is true and AGE is found, add age and reset f

Upvotes: 4

Related Questions