Which Row is the Key On?

JavaScript (ES6), 105 102 101 bytes

c=>/[~`0-9!@#-&^(-+_=-]/.test(c)+/[asdfghjkl;:'"\n]/i.test(c)*3+/[zxcvbnm,<.>/?]/i.test(c)*4||++c*7^2

Explanation

In JavaScript test returns a boolean which acts the same as 1 or 0 so I multiply them by their row. Testing for row 2 took the most bytes so I used that one as the default if no others matched.

c=>
  /[~`0-9!@#-&^(-+_=-]/.test(c)   // row 1 regex
  +/[asdfghjkl;:'"\n]/i.test(c)*3 // row 3 regex
  +/[zxcvbnm,<.>/?]/i.test(c)*4   // row 4 regex
  ||++c                           // space ++ = 1, any character on row 2 ++ = NaN
    *7^2                          // 7 XOR 2 = 5, NaN XOR 2 = 2

Test

var solution = c=>/[~`0-9!@#-&^(-+_=-]/.test(c)+/[asdfghjkl;:'"\n]/i.test(c)*3+/[zxcvbnm,<.>/?]/i.test(c)*4||++c*7^2
<textarea id="input">-</textarea><br />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>


Pyth, 62 66 65 bytes

?zh@+,4Zmid2c.Bi."0fÀÓ¸[9Ѷ¤KïLäHÉðbÀ`]ü©¬vS"16 2-CzCd3

Try it online.

Uses a packed string representing a number in hex which, when chopped into two-bit chunks, represents the row of every character except and ! as a value from 0 to 3. We leave out and ! so we don't have to store 4 or have a 0 at the start of this number, then add their row values using +,4Z. Once we've turned the string into row values, all we have to do is use the character code of the input to index into the array of values, and then add 1.

Newline is handled separately because it's interpreted by Pyth as an empty string and so has a character code of 0.

This would be shorter if I could figure out how to use base 256 in Pyth, but I can't quite make it work.


Glava 1.5, 164 bytes

Glava is a dialect of Java that makes Java code shorter. This code is unfortunately non-competitive as the commit (2 hours late...) used was made after this challenge, which fixed some vital bugs that would not allow this program to work.

p(A[0].matches("[`0-9-=~!@#$%^&*()_+]")?1:A[0].replace("\\n","\n").matches("(?i)[asdfghjkl;':\"\n]")?3:A[0].matches("(?i)[zxcvbnm,.\\/<>?]")?4:A[0].matches(" ")?5:2

This is a full program that takes input via command-line arguments. Works by simply testing for which row regex it matches, then outputs the corresponding number.