Write a function that applies a Caesar cipher shift to a string. Given a string s and an integer k, shift each alphabetic character in s forward by k positions in the alphabet, wrapping around if necessary. Preserve the case of letters (uppercase stays uppercase, lowercase stays lowercase) and leave non-letter characters unchanged. The shift k may be positive, negative, or larger than 26.
("Hello, World!", 3)'Khoor, Zruog!'