Home > database >  grep/sed/awk - Replace all "$X" in file with new computed value "$X/10"
grep/sed/awk - Replace all "$X" in file with new computed value "$X/10"

Time:11-21

This is my original file:

#Game No : 1000693
***** 888poker Hand History for Game 1000693 *****
$1/$2 Blinds No Limit Holdem - *** 18 11 2021 10:41:44
Table DD Poker 9 Max (Real Money)
Seat 7 is the button
Total number of players : 9
Seat 1: Monroe ( $2 )
Seat 2: Mpeti ( $2 )
Seat 3: Bowen ( $2 )
Seat 4: Riccardo ( $2 )
Seat 5: Ramman ( $2 )
Seat 6: Reva ( $2 )
Seat 7: Miklos ( $2 )
Seat 9: Samlet ( $2 )
Seat 10: Geralyn ( $2 )
Hamlet posts small blind [$1]
Geralyn posts big blind [$2]
** Dealing down cards **
Monroe calls [$2]
Mpeti folds
Bowen folds
Riccardo folds
Ramman folds
Reva folds
Miklos calls [$2]
Hamlet folds
** Dealing flop ** [ As, 6s, Ah ]
** Dealing turn ** [ 8s ]
** Dealing river ** [ 4h ]
** Summary **
Monroe shows [ Jh, Td ]
Miklos shows [ Tc, Jc ]
Samlet shows [ Th, 8c ]
Geralyn shows [ Js, Ts ]
Geralyn collected [ $17 ]

For all the dollar values "$X" I need to replace them with "$X/10" (Eks. $2/10=0.2) I am able to extract the dollar values and divide them with 10 with this piped command:

grep -o '\$[[:digit:]]*' dollar.txt | sed 's/[^0-9]//g' | awk '{print $1/10}'

0.1
0.2
0.2
0.2
0.2
0.2
0.2
0.2
0.2
0.2
0.2
0.1
0.2
0.2
0.2

How can I alter the whole original file (or create a new file) so that the rest of the file consist while all the "$X" values are replaced with "$X/10"?

CodePudding user response:

If you can use perl for this, the solution will be as short as

perl -i -pe 's{\$(\d )}{($1/10)}ge' file

See the online demo. Details:

  • -i - inline file changing option
  • s{\$(\d )}{($1/10)}ge - a substitution command, where the RHS (replacement part) is a Perl expression (this is enabled with the e flag), matching all (g) occurrences on each line of a $ symbol and then one or more digits (captured into Group 1, $1), and replacing each match with the result of division of the Group 1 value by 10.

If you want to explicitly forbid to perform substitution of float values (e.g. as in $10.500), you can replace \$(\d ) with \$(\d )(?!\.?\d).

CodePudding user response:

One implementation of this, as a pure awk script (no bash required), might look like:

#!/usr/bin/env awk -f
/[$][[:digit:]] / {
  while (match($0, /[$][[:digit:]] /) > 0) {
    prefix = substr($0, 1, RSTART-1)
    suffix = substr($0, RSTART RLENGTH)
    input = substr($0, RSTART 1, RLENGTH-1)
    output = input / 10
    $0 = prefix output suffix
  }
}
{ print }

If run with ./awkscript <in.txt or awk -f awkscript <in.txt, output is:

#Game No : 1000693
***** 888poker Hand History for Game 1000693 *****
0.1/0.2 Blinds No Limit Holdem - *** 18 11 2021 10:41:44
Table DD Poker 9 Max (Real Money)
Seat 7 is the button
Total number of players : 9
Seat 1: Monroe ( 0.2 )
Seat 2: Mpeti ( 0.2 )
Seat 3: Bowen ( 0.2 )
Seat 4: Riccardo ( 0.2 )
Seat 5: Ramman ( 0.2 )
Seat 6: Reva ( 0.2 )
Seat 7: Miklos ( 0.2 )
Seat 9: Samlet ( 0.2 )
Seat 10: Geralyn ( 0.2 )
Hamlet posts small blind [0.1]
Geralyn posts big blind [0.2]
** Dealing down cards **
Monroe calls [0.2]
Mpeti folds
Bowen folds
Riccardo folds
Ramman folds
Reva folds
Miklos calls [0.2]
Hamlet folds
** Dealing flop ** [ As, 6s, Ah ]
** Dealing turn ** [ 8s ]
** Dealing river ** [ 4h ]
** Summary **
Monroe shows [ Jh, Td ]
Miklos shows [ Tc, Jc ]
Samlet shows [ Th, 8c ]
Geralyn shows [ Js, Ts ]
Geralyn collected [ 1.7 ]

CodePudding user response:

I would use GNU AWK for this task following way, let file.txt content be

#Game No : 1000693
***** 888poker Hand History for Game 1000693 *****
$1/$2 Blinds No Limit Holdem - *** 18 11 2021 10:41:44
Table DD Poker 9 Max (Real Money)
Seat 7 is the button
Total number of players : 9
Seat 1: Monroe ( $2 )
Seat 2: Mpeti ( $2 )
Seat 3: Bowen ( $2 )
Seat 4: Riccardo ( $2 )
Seat 5: Ramman ( $2 )
Seat 6: Reva ( $2 )
Seat 7: Miklos ( $2 )
Seat 9: Samlet ( $2 )
Seat 10: Geralyn ( $2 )
Hamlet posts small blind [$1]
Geralyn posts big blind [$2]
** Dealing down cards **
Monroe calls [$2]
Mpeti folds
Bowen folds
Riccardo folds
Ramman folds
Reva folds
Miklos calls [$2]
Hamlet folds
** Dealing flop ** [ As, 6s, Ah ]
** Dealing turn ** [ 8s ]
** Dealing river ** [ 4h ]
** Summary **
Monroe shows [ Jh, Td ]
Miklos shows [ Tc, Jc ]
Samlet shows [ Th, 8c ]
Geralyn shows [ Js, Ts ]
Geralyn collected [ $17 ]

then

awk 'BEGIN{FPAT="[^0-9]|([0-9]*)";OFS=""}{dollar=0;for(i=1;i<=NF;i =1){if(dollar){$i*=0.1};dollar=($i=="$")};print}' file.txt

output

#Game No : 1000693
***** 888poker Hand History for Game 1000693 *****
$0.1/$0.2 Blinds No Limit Holdem - *** 18 11 2021 10:41:44
Table DD Poker 9 Max (Real Money)
Seat 7 is the button
Total number of players : 9
Seat 1: Monroe ( $0.2 )
Seat 2: Mpeti ( $0.2 )
Seat 3: Bowen ( $0.2 )
Seat 4: Riccardo ( $0.2 )
Seat 5: Ramman ( $0.2 )
Seat 6: Reva ( $0.2 )
Seat 7: Miklos ( $0.2 )
Seat 9: Samlet ( $0.2 )
Seat 10: Geralyn ( $0.2 )
Hamlet posts small blind [$0.1]
Geralyn posts big blind [$0.2]
** Dealing down cards **
Monroe calls [$0.2]
Mpeti folds
Bowen folds
Riccardo folds
Ramman folds
Reva folds
Miklos calls [$0.2]
Hamlet folds
** Dealing flop ** [ As, 6s, Ah ]
** Dealing turn ** [ 8s ]
** Dealing river ** [ 4h ]
** Summary **
Monroe shows [ Jh, Td ]
Miklos shows [ Tc, Jc ]
Samlet shows [ Th, 8c ]
Geralyn shows [ Js, Ts ]
Geralyn collected [ $1.7 ]

Explanation: I inform GNU AWK that field is either (0 or more digits) or single any other character using FPAT. Then I iterate over fields using for loop, firstly I replace field with 0.1 of value if dollar variable holds true, then I set dollar variable to true if field is equal to $. Order is crucial, as this mean first operation is to field immediately after dollar field. After processing all fields in line I print it. I set output field separator (OFS) to empty string, to prevent injecting unwanted characters.

(tested in GNU Awk 5.0.1)

CodePudding user response:

If .2 is sufficient for 0.2, you could just put a dot before the last digit of each dollar value:

sed -E 's/(\$)([0-9]*)([0-9])/\2.\3/g

Otherwise:

sed -E '
    s/(\$[0-9]*)([0-9])/\1.\2/g
    s/(\$)(\.[0-9])/\10\2/g
    s/(\$)([0-9])/\2/g'
  • Put a dot before the last digit of each dollar value
  • Add a 0 before the dot if necessary
  • Remove $
  • This won't work if the input can contain decimal dollar values already (like $10.00)
  • Related