4

I am trying to delete a numerical value once only from a file where there could be more than one instance of that value. file_input=

2  
4  
18  
8  
8  
10  
12  
14  

I need to delete '8' but only once and i want to keep '18'. The final result should be in file_output as such:

2  
4  
18  
8  
10  
12  
14  

I tried sed '/8/d', grep -v -w '8' and awk '$1 !=8' but they all delete 8, 8, and 18.

Joshua
  • 34,237
  • 6
  • 59
  • 120
user312288
  • 63
  • 6
  • Please take a look at: [What should I do when someone answers my question?](http://stackoverflow.com/help/someone-answers) – Cyrus Dec 28 '17 at 14:14
  • How to replace '8' by a var such as $number as this function can be called to delete a different number when used? – user312288 Dec 28 '17 at 20:07
  • With a variable: `n="8"; sed '1,/^'"$n"'$/{/^'"$n"'$/d}' file` – Cyrus Dec 28 '17 at 21:29

2 Answers2

2

I suggest with GNU sed:

sed '1,/^8$/{/^8$/d}' file

Output:

2
4
8
10
12
14

From first line to line which contains only 8 (1,/^8$/) delete line which contains only 8 (/^8$/d).


See: man sed and The Stack Overflow Regular Expressions FAQ

Cyrus
  • 69,405
  • 13
  • 65
  • 117
  • This works as I want even if I add 88 before the value 8. Wonderful, thanks. – user312288 Dec 28 '17 at 14:09
  • When you have to write the same code multiple times (e.g. `/^8$/` twice in this case), it means you should look for a different solution. – Ed Morton Dec 28 '17 at 15:27
1

Here's the awk version

$ awk '!($1==8 && !c++)' ip.txt
2  
4  
18  
8  
10  
12  
14  
  • $1==8 && !c++ check if first field is exactly 8, if so check whether c evaluates to false(c will get incremented and so won't be false next time)
    • we don't want to print when this is true, hence the outer negation
  • this will work even if there are whitespaces around the first field, like in the given sample in question
Sundeep
  • 19,273
  • 2
  • 19
  • 42