0

Playing with sed - the commands below do what's required but one liners would be better. I have tried combining the first two commands (with a separating ';') to remove the trailing ':' without success. Otherwise, resorted to removing the last ':' and writing to a new file to perform the next operation.

File 'sys' with a single line containing a variable number characters and ':' separator. For example;

Input - 'sys' first line 3.000000:50: desired output, two variables thd=3 mem=50

thd=$(echo | sed 's/.......:.*//' < sys)
sed 's/:$//' < sys > sys1
mem=$(echo | sed 's|........:||' < sys1)

Is there a way to combine the first two sed commands to avoid writing a second file? I have tried this various ways

Something like this - EDIT: this is the wrong order to remove the trailing ':'

thd=$(echo | sed 's/:$//;s/.......:.*//' < sys)
mem=$(echo | sed 's|........:||' < sys1)

Output 3 50: with the separator attached.

EDIT: This is the correct order and produces the desired output. Bash does not save the result of the first operation in the file sys. Which I should have picked up in the 3 liner.

thd=$(echo | sed 's/.......:.*//' < sys)
mem=$(echo | sed 's|........:||;s/:$//' < sys)
GeorgeC
  • 81
  • 2
  • 9

2 Answers2

1

If you need two variables to be assigned values independently, the first containing the number before the point and the second the number between the colons, you can use an approach like

thd=$(cut -f1 -d. < sys)
mem=$(cut -f2 -d: < sys)

Assigning both at the same time is also possible:

read thd mem < <(tr "." ":" < sys | cut -f1,3 -d: --output-delimiter=" ")
Poshi
  • 5,332
  • 3
  • 15
  • 32
  • The cut version is ideal. Just a few characters. – GeorgeC Aug 28 '18 at 15:38
  • the read version requires the `tr -d` option. Still couldn't get it to work on my system. – GeorgeC Aug 29 '18 at 08:13
  • If you use the `-d` option of `tr`, you will delete the separators and lose the information needed for proper field separation. – Poshi Aug 29 '18 at 08:48
  • As you say `-d` doesn't work - this does `read thd mem < <(cut -f1,2 -d: --output-delimiter=" " < sys)` if happy to accept the trailing `.000000`, which makes no difference in my application - no need for the `tr` options in that case. – GeorgeC Aug 29 '18 at 11:25
1

Try this:

$ echo '3.000000:50:' | { IFS='.:' read thd x mem; echo "'$thd' '$mem'"; }
'3' '50'

Or this:

$ sys='3.000000:50:'; IFS='.:' read thd x mem <<< "$sys"; echo "'$thd' '$mem'"
'3' '50'

The above sets the "dont care" variable x. If you do not like that, you can assign mem twice.

$ sys='3.000000:50:'; IFS='.:' read thd mem mem <<< "$sys"; echo "'$thd' '$mem'"
'3' '50'
ceving
  • 21,900
  • 13
  • 104
  • 178
  • To read the file `sys` something like this `$ { IFS='.:' read thd x mem; echo "'$thd' '$mem'"; } < sys` Which I found more difficult with multiple fields to read. – GeorgeC Aug 29 '18 at 20:37
  • The advantage of `read` is, that it does not require two sub shells and two `cut` calls. – ceving Aug 30 '18 at 07:16
  • I have played around with this one '{ IFS='.:' read thd x mem x img x cal; echo "'$thd' '$mem' '$img' '$cal' "; } < sys' how does the don't care variable work? – GeorgeC Aug 30 '18 at 08:58
  • Should be `{ IFS='.:' read thd x mem x img x cal; echo "'$thd' '$mem' '$img' '$cal' "; } < sys` how does the don't care variable work? – GeorgeC Aug 30 '18 at 09:14
  • When you split with `IFS='.:'`, you get three tokens: 3, 000000 and 50. Each token gets stored in one variable: `thd=3`, `x=000000` and `mem=50`. You have to store the zeros somewhere, although you do not need them. You can also do `unset x` after the `read`. Or you can assign `mem` twice. First with the zeros and then with the 50. – ceving Aug 30 '18 at 09:30
  • Thanks. Got it. This `echo 3.000000:50:raw:TRUE: > sys` `{ IFS='.:' read thd x mem img cal; echo "'$thd' '$mem' '$img' '$cal'"; } < sys` returns `'3' '50' 'raw' 'TRUE'` awesome! – GeorgeC Aug 30 '18 at 20:53
  • And this - `echo 3.000000:50:raw:TRUE:4.000000 > sys` `{ IFS='.:' read thd x mem img cal cor x ; echo "'$thd' '$mem' '$img' '$cal' '$cor' "; } < sys returns '3' '50' 'raw' 'TRUE' '4'` – GeorgeC Aug 30 '18 at 21:06