Here is a circuit I use to generate a clean logic signal to a shift register from an insulated rail:
Note that I use an RC debounce and feed the signal into a Schmitt trigger buffer to generate a clean transition from a noisy signal. This takes care of the AC ripple as well as intermittent contact between the wheels and the third rail.
Debouncing and filtering could be performed in software, but I originally built the circuit for a microcontroller that had very little memory or processing power, so software debouncing wasn't an option.