0

I am trying to create a file that contains all numbers between 1 and 100, each number in a single line, but with all multiples of 7 substituted by 7:

...
12
13
7
15
16
...

My current code is the following, but the sed command does not work well,

$sudo seq 1 100 | sed -e 's/$?{%7==0}/7/g' > check.txt

How should I write math operations in sed?

Enlico
  • 23,259
  • 6
  • 48
  • 102
riki
  • 19
  • 7

4 Answers4

3

You can't do arithmetic operations in sed, but you can implement them to some extent with existing features, like:

seq 100 | sed '7~7s/.*/7/'

With awk that would be:

awk 'BEGIN { for (i=1;i<=100;i++) print i%7?i:7 }'
oguz ismail
  • 1
  • 16
  • 47
  • 69
  • thank you so much! if you can explain the expression '7~7s/.*/7/' it will be great! – riki Dec 09 '19 at 18:51
  • @riki it's easy, `7~7` means; beginning from seventh line, do the following for every seventh line; in this case the operation is `s/.*/7/`, which simply means replace the whole line with just 7. – oguz ismail Dec 09 '19 at 18:57
  • WoW! great explanation. do u have an idea how can I cut with number delimiter? I mean- I want to write this way: ... | cut -d '[0-9] but cut does not receive a regex as delimiter. – riki Dec 09 '19 at 19:22
  • @riki I didn't understand what you meant, could you elaborate with an example? – oguz ismail Dec 09 '19 at 19:27
  • 2
    Probably useful to point out that notation like `7~7` is specific to GNU sed, and not portable to sed in other operating systems. (For example, macOS, FreeBSD, etc). – ghoti Dec 09 '19 at 19:31
  • @ghoti exactly, the sed solution above is GNU-specific – oguz ismail Dec 09 '19 at 19:35
  • @ oguz ismail : i mean that i want do display the second part of words: yyy2r, ttt3i and so on... i want from the number and right – riki Dec 09 '19 at 21:01
  • @riki that's another question – oguz ismail Dec 10 '19 at 03:30
1

Sed can't do arithmetics, but Perl can. It can also do a sequence, so no need for seq and a pipe:

perl -le 'print $_ % 7 ? $_ : 7 for 1 .. 100'

It uses the ternary operator ?: which evaluates the condition ($_ % 7 here, i.e. the modulo) and returns the second parameter if it's true, or the third parameter otherwise. -l adds a newline to each print.

choroba
  • 231,213
  • 25
  • 204
  • 289
0

I love sed, but I think this is more a job for awk:

seq 1 100 | awk '{ if ($1 % 7 == 0) { print 7; } else { print $0; } }'
Enlico
  • 23,259
  • 6
  • 48
  • 102
  • 1
    If you're gonna use awk, why do you need seq at all? – oguz ismail Dec 09 '19 at 19:21
  • Good point. Everything could be in a `for` loop in `BEGIN`/`END`. I just wanted to keep the source of the numbers separated. But maybe it doesn't even make sense, you're right. – Enlico Dec 09 '19 at 19:57
0

Actually plain bash can handle this too:

for i in $(seq 1 100); do (( i % 7 )) && echo $i || echo 7; done
Enlico
  • 23,259
  • 6
  • 48
  • 102
  • 1
    For a simple static example of numbers from 1 to 100, why not just go with `{1..100}` rather than spawning a subshell? – ghoti Dec 10 '19 at 02:04