Search code examples
textsedcommand-linetext-parsing

Line number and negated search combination in sed


I have a CSV whose tail is missing column data, e.g. the following:

Data1,Data2,User
abc,def,foo
hij,klm,foo
nop,qrs
tuv,wxy

In this case, I want to add bar to the end of the rows without foo. That's easily accomplished with sed '/foo/!s/$/,bar/'. The issue is that this will add a ,bar to the first line as well. I know that I can skip the first line with a 2,$ but when I do that it seems to not respect both "line number" and "negated search" instructions. Is there a way inside sed to incorporate both?

(To be clear, I know I have other options. I can probably do multiple sed operations, or I can write a simple macro in vim and be done in a second as well. But in this case, I want to see if it can be done entirely in a single sed.)


Solution

  • Here is a sed command that should work with any version of sed:

    sed '2,${ /foo/!s/$/,bar/; }' file
    
    Data1,Data2,User
    abc,def,foo
    hij,klm,foo
    nop,qrs,bar
    tuv,wxy,bar
    

    If you want to give awk a chance then it is much easier with any version of the awk:

    awk 'NR > 1 && !/foo/ {$0 = $0 ",bar"} 1' file
    
    Data1,Data2,User
    abc,def,foo
    hij,klm,foo
    nop,qrs,bar
    tuv,wxy,bar