2

I have created a 0,1,2 genotype matrix and I want to replace all of the -1 with 9.

0   0   -1  0   0   0   0   2   0   0   0   0   -1
0   0   1   0   0   0   0   0   0   0   0   -1   1
0   0   2   0   0   -1  2   0   0   0   -1  0    0

I tried this:

sed -ie 's/^[-1] /9 /' file1 > file2

but it seems that it does not work.

Is there any way to do that?

1
  • 2
    The [] enclose a collection of characters, so each occurrence of either - or 1 matches, but the ^ anchors the expression to the beginning of the line, so you don't get any match. You also miss the g flag to handle multiple occurences in a line.
    – Philippos
    Commented Aug 3, 2017 at 7:08

5 Answers 5

1
sed 's/-1/9/g' file > file2
2
  • Place a space behind the 9 or you'll break the columns.
    – Philippos
    Commented Aug 3, 2017 at 7:09
  • What about some number -10?
    – Kusalananda
    Commented Apr 23, 2021 at 20:35
1
sed -i 's/-1/9 /g' file
sed 's/-1/9 /g' file1 > file2
1
  • This would affect any field that starts with -1, e.g. -11.
    – Kusalananda
    Commented Apr 23, 2021 at 20:35
0

To do it in safe manner:

sed -e '
   s/$/ /
   :a;s/ -1 / 9 /;ta
   s/.$//
' file1

where

  • s/$/ / insert a space at end of line
  • :a;s/ -1 / 9 /;ta do substitution (space is needed if -1 at end of line)
  • s/.$// remove space from end of line
0

Your command,

sed -ie 's/^[-1] /9 /' file1 > file2

does not work for two main reasons:

  1. It changes the file in-place and backs the original up as file1e. It does this because you instruct sed to use the letter e as the backup prefix when you use -ie. You file2 file will be empty since the result is written back into file1.

  2. Your regular expression, ^[-1] , does not match anything. The ^ will anchor the expression at the very start of the line, and in the example data that you have provided, the character at the start of each line is 0.

    • Fixing this by removing ^ does not work, because [-1] only matches a single character, either a - or a 1. This means that the sed expression s/[-1] /9 / would replace the first - or 1 followed by a space on each line with 9 followed by a space.

    • Adding the /g flag at the end would not help as this would still erroneously replace any 1 that is not -1, and it would additionally fail to replace an -1 at the very end of the line where there is no trailing space.

Instead, substitute each -1 with 9, and also be careful with not replacing the -1 substring of numbers such as -10:

sed 's/-1\>/9/g' file1 >file2

The expression -1\> will match the string -1 wherever it occurs with no trailing word characters (letters or digits). It will therefore not match -10 or -11 etc.

Since you seem to want to write the result to file2, I don't use the -i option for in-place editing. I also don't need to use an -e option to specify the sed expression, as there is only one expression.


To not have to bother about regular expressions, you laso have the option of using awk to replace the numbers:

awk '{ for (i=1; i<=NF; ++i) if ($i == -1) $i = 9 }; 1' file1 >file2

This iterates over each whitespace-delimited field on each line and replaces each that is numerically equal to -1 with 9.

This would replace the field delimiter on each modified line with a space. If you want to use another delimiter than space, set tho OFS variable on the command line:

awk -v OFS='\t' '{ for (i=1; i<=NF; ++i) if ($i == -1) $i = 9 }; 1' file1 >file2
-4

I found the answer

sed -E 's/[-1] / 9/' file1 > file2

can do the job

1
  • No, sorry, it can't. [-1] matches a single character, a dash or a 1.
    – Kusalananda
    Commented Apr 23, 2021 at 20:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .