2

as tittle, how sed perform "greater than" to delete specific line?
I got a file like this:

bash-4.2$ cat testfile.txt
string1 1 1
AAA 2 2
string2 2 2
BBB 3 3
string3 3 3
string4 4 4
string5 5 5
string6 6 6
CCC 6 6
string7 7 7
string8 8 8
string9 9 9
string10 10 10
DDD 11 11
string11 11 11
string12 12 12
string13 13 13

I wanna delete some lines which contains "string[[:digit:]]" but string1 to string"$num" is needed, num is defined by a variable. For example, I wanna keep those lines which contains string1-5 and delete string6-string99, I'd tried:

#!/bin/bash
read -p "Please Assign the Number of String Line that You Wanna Keep: " num
cat testfile.txt | sed -e "/string[`expr $num + 1`-9]/d" > new_testfile.txt

but it's only working in range 0-8, is there any way to perform it with sed or awk?

liltme
  • 91
  • 7

3 Answers3

3

This 'awk` should do:

awk '/^string/ {n=substr($1,7)+0;if (n>5 && n<100) next}1' file
string1 1 1
AAA 2 2
string2 2 2
BBB 3 3
string3 3 3
string4 4 4
string5 5 5
CCC 6 6
DDD 11 11

It just skips any line with string"x" where x is larger then 5 and less then 100


If high/low comes from variables, this should do:

high=99
low=6
awk '/^string/ {n=substr($1,7)+0;if (n>=l && n<=h) next}1' h="$high" l="$low" file
string1 1 1
AAA 2 2
string2 2 2
BBB 3 3
string3 3 3
string4 4 4
string5 5 5
CCC 6 6
DDD 11 11
Jotne
  • 40,548
  • 12
  • 51
  • 55
  • It is worth pointing out that the `1` at the end of the script is `awk` shorthand for `else print $0;` - in other words, "for all lines that didn't match the earlier regex, use the default action of printing the entire line" – Floris Mar 26 '14 at 11:37
  • @Floris Not quite correct. `1` does mean print the current line, same as `1 {print $0}'`. There are no `else` involved. If the expression in front hits the `next`, it will skip to next line and not use the `1` – Jotne Mar 26 '14 at 11:47
  • I was trying to simplify. You are right this is only true because of the `next` inside the preceding statement. It was really meant as an invitation to you to clarify your answer - specifically the 'magical 1' that confuses a lot of people when they first meet `awk` – Floris Mar 26 '14 at 15:02
  • No problem, is see many people asking about the `1`. Even more while some use `7` ;) – Jotne Mar 26 '14 at 15:23
  • Personally I prefer using 42. Works just the same but really confuses people. :-) – Floris Mar 26 '14 at 19:31
  • @Floris Life Universe Every thing etc. http://www.bbc.co.uk/programmes/articles/1g84m0sXpnNCv84GpN2PLZG/the-hitchhiker-s-guide-to-the-galaxy-game-30th-anniversary-edition – Jotne Mar 26 '14 at 20:03
  • 1
    indeed, it is the answer. But what is the question? Did you see http://codegolf.stackexchange.com/questions/21835/most-creative-way-to-display-42 ? I loved the one that did `#define SIX 1 + 5; #define NINE 8 + 1; printf("six times nine is %d\n", SIX * NINE);`... - you really need to have read the books to understand how clever it is. – Floris Mar 27 '14 at 02:08
  • thanks guys, the "1" did confuse me, but I just read the article @Floris provied, well, I'll go 42 from now on! – liltme Mar 27 '14 at 08:41
1

Here is one way with awk:

$ read -p "Please Assign the Number of String Line that You Wanna Keep: " num
Please Assign the Number of String Line that You Wanna Keep: 5
$ awk -v max="$num" '/string/{line=$0;sub(/string/,"",$1);if($1+0<=max){print line};next}1' file
string1 1 1
AAA 2 2
string2 2 2
BBB 3 3
string3 3 3
string4 4 4
string5 5 5
CCC 6 6
DDD 11 11
jaypal singh
  • 74,723
  • 23
  • 102
  • 147
0

This is an old question, but if you are coming from a duplicate, perhaps the important thing to understand is that sed does not have any facilities for arithmetic, which is why all the old answers here use Awk.

If you can articulate a regex which reimplements your mathematical constraint as a textual constraint, these things are possible;

sed 's/string\([1-9][0-9]\+\|[6-9]\)//' testfile.txt

To briefly spell this out, this finds and replaces string if it is followed by two or more digits, or a single digit which is 6-9, which implements the requirement by matching the digits as string sequences.

GNU sed also has a limited facility for executing external commands on the matched text with the non-standard flag /e, but my advice would be to switch to Awk at that point anyway, which allows you to reason about mathematical properties of numbers with a more readable and beginner-friendly syntax as well as vastly better efficiency by way of avoiding to spawn an external process for each expression you want to evaluate.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Perhaps notice also how this avoids a [useless use of `cat`](https://stackoverflow.com/questions/11710552/useless-use-of-cat) – tripleee May 09 '22 at 07:04