0

I recently asked a question very similar to this one but failed to provide enough feedback for what would be a solution for this particular case. Opening this question with further information and context.

I have two files:

File1:

not_keyword: 'something'
keyword: 'condition'
another_not_keyword: 'something'

File2:

condition 1 condition 2 condition 3

I would like to find all occurrences of keyword in File1 and replace its content (condition) with the content of File2.

Desired output in this case:

not_keyword: 'something'
keyword: 'condition 1 condition 2 condition 3'
another_not_keyword: 'something"

It's my intent to have the replacement happen in place (directly on the file itself). A solution using gawk was given, but unfortunately I can't use anything other than sed or awk.

2
  • Will there always be only one line in file2? Commented Jan 21, 2020 at 16:33
  • @RomanPerekhrest yes.
    – t988GF
    Commented Jan 21, 2020 at 17:09

3 Answers 3

1

Awk approach:

awk '$1=="keyword:"{ getline k < "file2"; print $1, "\047" k "\047"; next }1' file1

The output:

not_keyword: 'something'
keyword: 'condition 1 condition 2 condition 3'
another_not_keyword: 'something'

As an alternative use sed in-place substitution:

$ sed -Ei "s/^(keyword: ).*/\1'$(cat file2)'/" file1
5
  • This provides the correct output put not directly in the file (in place). Any chance I can do changes in the file without having to use gawk?
    – t988GF
    Commented Jan 21, 2020 at 18:53
  • @t988GF, have you tried awk '<command>' file1 > tmp1 && mv tmp1 file1 ? Commented Jan 21, 2020 at 19:11
  • @t988GF, see my update Commented Jan 21, 2020 at 19:15
  • Getting -e expression #1, char 81: unknown option to `s' (on GNU sed 4.4) @RomanPerekhrest
    – t988GF
    Commented Jan 21, 2020 at 19:27
  • the sed script will fail cryptically for various contents of file2, e.g. / or & or \2 or $ or... The awk script with getline has issues too, see awk.freeshell.org/AllAboutGetline, but they're less likely to occur.
    – Ed Morton
    Commented Jan 22, 2020 at 15:13
1
$ cat tst.awk
NR == FNR {
    new = (NR>1 ? new ORS : "") $0
    next
}
$1 == "keyword:" {
    $0 = $1 OFS "\047" new "\047"
}
{ print }

$ awk -f tst.awk file2 file1
not_keyword: 'something'
keyword: 'condition 1 condition 2 condition 3'
another_not_keyword: 'something'
2
  • Thank you Ed, this replaces the text as expect. Would there be a way to make it a bit more "portable", without requiring the .awk file? Also, is it possible to replace inline? As I mentioned in the post using gawk for inline is not possible.
    – t988GF
    Commented Feb 10, 2020 at 10:51
  • Just do awk 'NR == FNR { new = (NR>1 ? new ORS : "") $0; next } $1 == "keyword:" { $0 = $1 OFS "\047" new "\047" } { print }' file2 file1. When you say "replace inline" - do you mean modify one of the original input files? If so, which one? In any case, you'd just do awk 'script' file > tmp && mv tmp file - that's all that any of the "inplace" editing tools do internally anyway.
    – Ed Morton
    Commented Feb 10, 2020 at 14:38
0

The question asks for a solution using a YAML-unaware tool. I'm giving a solution using yq by Andrey Kislyuk (not Mike Farah's yq), which is YAML-aware:

yq -Y '.keyword = input' file newdata

The output, given the data in the question:

not_keyword: 'something'
keyword: 'condition 1 condition 2 condition 3'
another_not_keyword: 'something'

You may use -i or --in-place to make an in-place edit.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .