Reputation: 91
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?
Upvotes: 2
Views: 592
Reputation: 189679
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.
Upvotes: 0
Reputation: 41460
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
Upvotes: 3
Reputation: 77145
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
Upvotes: 1