5

I have a file that I need to multiply each number with -1. I have tried some commands but the result I get every time is only the first column multiplied with -1. Please help!

The file is as follows:

-1 2 3 -4 5 -6
7 -8 9 10 12 0

The expected output would be

1 -2 -3 4 -5 6
-7 8 -9 -10 -12 0

Commands I have tried are:

awk '{print $0*-1}' file
sed 's/$/ -1*p /' file  | bc (syntax error)
sed 's/$/ * -1 /' file  | bc (syntax error)
numfmt --from-unit=-1 < file (error: numfmt: invalid unit size: ‘-1’)
Cyrus
  • 84,225
  • 14
  • 89
  • 153
Elena
  • 61
  • 4

8 Answers8

6

With bash and an array:

while read -r -a arr; do
  declare -ia 'arr_multiplied=( "${arr[@]/%/*-1}" )';
  echo "${arr_multiplied[*]}";
done < file

Output:

1 -2 -3 4 -5 6
-7 8 -9 -10 -12 0

I got this idea from this Stack Overflow answer by j4x.

Cyrus
  • 84,225
  • 14
  • 89
  • 153
  • That's a neat trick. Had no idea you can use integer attributes with arrays. – Shawn Jan 09 '23 at 17:57
  • @Shawn: I still had in mind that it is possible to apply an operation to all elements of an array. [j4x](https://stackoverflow.com/a/46242196/3776858) had the right answer. – Cyrus Jan 09 '23 at 18:05
4

One awk approach:

$ awk '{for (i=1;i<=NF;i++) $i=$i*-1} 1' file
1 -2 -3 4 -5 6
-7 8 -9 -10 -12 0

Using the <var_or_field><op>=<value> construct:

$ awk '{for (i=1;i<=NF;i++) $i*=-1} 1' file
1 -2 -3 4 -5 6
-7 8 -9 -10 -12 0
markp-fuso
  • 28,790
  • 4
  • 16
  • 36
3

Using perl and its autosplit mode:

perl -lane 'print join(" ", map { $_ * -1 } @F)' file
Shawn
  • 47,241
  • 3
  • 26
  • 60
1

To multiply every number in the file with -1, you can use the following 'awk'command:

   `awk '{ for (i=1; i<=NF; i++) $i=$i*-1; print }' file`

This command reads each line of the file, and for each field (number) in the line, it multiplies it by -1. It then prints the modified line.

The output will be as follows:

    1 -2 -3 4 -5 6
    -7 8 -9 -10 -12 0

Alternatively, you can use the following 'sed' command:

   sed 's/-\([0-9]*\)/\1/g; s/\([0-9]*\)/-\1/g' file

This command replaces all negative numbers with their positive equivalent, and all positive numbers with their negative equivalent. The output will be the same as above.

H.Elci
  • 216
  • 1
  • 5
1

For completeness an approach with ruby.

  • -l Line-ending processing
  • -a Auto-splitting, provides $F (field, set with -F)
  • -p Auto-prints $_ (line)
  • -e Execute code
ruby -lape '$_ = $F.map {|x| x.to_i * -1}.join " "' file
1 -2 -3 4 -5 6
-7 8 -9 -10 -12 0
Andre Wildberg
  • 12,344
  • 3
  • 12
  • 29
0

Just switching the signs ought to do.

$: cat file
1 -2 -3 4 -5 6
-7 8 -9 -10 -12 0

$: sed 's/^ */ /; s/  */  /g; s/  -/ /g; s/  / -/g; s/-0/0/g; s/^ *//;' file
-1 2 3 -4 5 -6
7 -8 9 10 12 0

If you don't care about leading spaces or signs on your zeros, you can drop some of that. The logic is flexible, too...

$: sed 's/ *-/+/g; s/ / -/g; s/+/ /g;' x
1 2 3 -4 5 -6
 7 -8 9 10 12 -0
Paul Hodges
  • 13,382
  • 1
  • 17
  • 36
0

There are multiple ways we can do this. I can think of the following 2 ways

cat file | awk '{for (i=1;i<=NF;i++){ $i*=-1} print}'

This will give out

1 -2 -3 4 -5 6
-7 8 -9 -10 -12 0

In this method we overwrite the $i value and print $0

Another way

cat random.xml | awk '{for (i=1;i<=NF;i++){printf("%d ",$i*-1)} printf("\n")  }'

Gives the output

1 -2 -3 4 -5 6
-7 8 -9 -10 -12 0

In this method we print the value $i*-1 and so we need to use printf() function

pss
  • 21
  • 4
0

don't "do math" and actually multiply by -1 -

just use regex to flip the signs, and process thousands or even millions of numbers with 3 calls to gsub()

RARE Kpop Manifesto
  • 2,453
  • 3
  • 11