0

How I can increment through clients seat_num using bash? I have this file:

$ cat test
    client1
    name="", possition="", seat_num=""
    client2
    name="", possition="", seat_num=""

I need this kind of increment:

client1
name="", possition="", seat_num="1"
client2
name="", possition="", seat_num="2"

I tried this approach, but it does not do what I wanted:

$ while read -r line; do i=1;echo $line|sed -e 's/seat_num=""/seat_num="$i"/';((i++)); done <<< "$(grep -A 2 client test)"
        client1
        name="", possition="", seat_num="$i"
        client2
        name="", possition="", seat_num="$i"
  • 1
    What is the start value of seat_num in test file? If it is not a number, it cannot be incremented. – sakkke Feb 18 '22 at 08:18
  • 1
    lets assume all clients in input file will have seat_num="1", how then it can be incremented for each client? Meaning that client1 should have seat_num="1", client2 - seat_num="2" ... – denys.by Feb 18 '22 at 08:25
  • 1
    Please don't add information in the comments, as it's all too easy to miss. Put everything in your question. Also, don't use "Edit" or "Update" to append details - but instead include the new information in your question as if you'd had it when you first posted. That way, it's much easier to read - and hopefully answer – Chris Davies Feb 18 '22 at 09:01
  • 1
    Your starting point seat_num="" isn't a number – Chris Davies Feb 18 '22 at 09:11

3 Answers3

0

seat_num starts 1.

You can try:

i=1
while IFS= read -r line; do
    if grep -Fq 'seat_num=""' <<< "$line"; then
        sed "s/seat_num=\"\"/seat_num=\"$((i++))\"/" <<< "$line"
    else
        printf '%s\n' "$line"
    fi
done <<< "$(grep -A 2 client test)"

Output:

client1
name="", possition="", seat_num="1"
client2
name="", possition="", seat_num="2"

i increments if line includes seat_num="".

sakkke
  • 193
  • 1
    I would like to increment it through clients. To increment through a file simple sed would be enough. I need this: client1 name="", possition="", seat_num="1" client2 name="", possition="", seat_num="2" – denys.by Feb 18 '22 at 09:03
  • Please ADD THIS TO YOUR QUESTION – Chris Davies Feb 18 '22 at 09:13
  • 1
    (1) Instead of grep > /dev/null, you can use grep -q. (2) As seat_num="" is a fixed string, you should use grep -F for performance reasons. (3) You could increment i directly by using $((i++)) inside your sed replacement string if you wish. (4) Better to use printf instead of echo. (5) To avoid issues if last line does not have newline, you should set IFS --> while IFS= read -r line; do – pLumo Feb 18 '22 at 10:33
  • Thank you helpful information! – sakkke Feb 19 '22 at 06:50
0

Use awk:

awk 'BEGIN{FS=OFS="\""} /seat_num=/{$6=++n}1' test
  • FS=OFS="\"" Set Input and Output Field Separator to ".
  • If seat_num= is found in a line, change 6th field to ++n.
  • var=++n means increment n first, then set var. Compared to var=n++ which would set var and increment afterwards. An undefined variable in awk has value of 0, so you want to increment first (--> ++n).

To edit your file in place, you could use -i inplace if available.
If not available, add > test.tmp && mv test.tmp test

pLumo
  • 22,565
0

Although your question specifies "incrementing" (to add to an existing number, often by 1), the impression I get from reading your other comments is that you would really like to iterate through the clients in a file and read the number after "client" in one row, and then make the seat_num in the following row equal to the same number.

If that is the case, then the following sed command works for me, where test has the same contents as in the question. (I'm sure there are plenty of other ways to do it):

sed 'H;1h;$!d;x; s/client\([0-9]*\)\(\n[^\n]*\)seat_num=""/client\1\2seat_num="\1"/g' <<< cat test

This starts with a magic string from @Wiktor Stribizew's answer to this SO question: "(H;1h;$!d;x; slurps the file into memory)". Reading the man page, I think it is copying the line of pattern read from the input into a "Hold space", then deleting the pattern and reading another line of pattern from the input until the input is ended, then swapping the "Hold space" back to the "Pattern space" ready to run the following substitution. However, I'm still not clear on the details, so I would be happy to be corrected.

In the substitution, we look for client followed by 0 or more digits ([0-9]*), and we use escaped parentheses \( and \) to remember the digits. Then we look for a newline followed by 0 or more not-newlines (so that we read only up to the next seat_num), followed by the next seat_num="" - again using escaped parentheses to remember what came before the seat_num=.

We replace all of this with the original client text and the remembered number (\1 uses the first remembered parameter) followed by the second remembered parameter, then the original seat_num=" text and a repeat of the first remembered parameter (the digit(s) after client) and the final ". As the pattern now contains the whole file, we use the g command to do this substitution globally.

mdmay74
  • 56