sed 's/\\\\/& /g;s/\\n/\
/g; s/\\\\ /\\\\/g' <in >out
...should handle the \newline replacements without misinterpreting backslash escapes - so you can still have a literal \\n in input. I'm a little fuzzy on how you can ever get a \n out of your history commands, though.
I tried w/ zsh to find out how a \newline might be read out from the history file without being escaped like that:
echo '
\n'
history -1
11355 echo '\n\n'
That won't do. So, I tried this instead:
hist(){ ! cat "$1"; }
echo '
\n'
FCEDIT=hist fc -1
echo '
\n'
...so that's probably what you should be doing instead
For some reason zsh escapes \newlines in history or fc -l output in an ambiguous way, but when it hands a history command over to some editor, it gives it the real thing.
zsh's primary means of history manipulation is fc, and the history command is not much more than an alias for fc -l. When fc is called with the -l option it will list the matching history lines to stdout (after ambiguously escaping any non-printable characters), but fc's default behavior is to invoke another utility with one or more temp file arguments into which it has written all history matches for its args.
fc derives the name of the utility it invokes from the $FCEDIT environment variable, or, if it is unset or null, from $EDITOR, or, if likewise unsuccessful, defaults to vi. If the invoked utility returns true, fc will afterward attempt to run any commands it finds in the (presumably) edited temp files before removing them.
And so the above command sequence substitutes cat for any editor command, and inverts its return so that a successful readout of fc's tempfiles will return false - to keep fc from trying to run the commands again.
A more complete, sort-of drop-in solution which doesn't need to call out to an external utility could look like:
history()
case $1 in
(*/*) ! while [ -r "$1" ]
do while read -rE RTN
do :; done <$1
shift; done;;
(*) local RTN=1 IFS=
FCEDIT=history fc "$@"
return $((RTN*$?))
esac
...which ought to handle almost transparently any argument list you might expect zsh's history command to do; except that its output is always literal and it never includes history timestamps or event numbers in the output (unless you call it like history -l [args], in which case it will behave as the builtin history).
sed, and you get\n? Or do you mean that the\nis coming fromawk? – Tom Zych Nov 21 '15 at 02:34sedorgsed... it has to do with the shell you are using and the expansion of"\n". Try the final-eoption to sed as-e 's/\\n/\n/g'(thegwill do all in the line rather than just the first, btw) (not confident this will work though). – Murray Jensen Nov 21 '15 at 02:50-eexpression that's failing. The rest is just for context. Instead of a newline, I'm getting annas the replacement with the code as shown if I use sed instead of gsed. But I tried lots of different things and none of them worked except using gsed. – iconoclast Nov 21 '15 at 03:12s///ubstitution. the portable way to do it is to backslash-escape a literal\newline character into the substitution. – mikeserv Nov 21 '15 at 03:14awkwhich you are using anyway portably (POSIXly) supports\nand friends on both pattern and substitute ofgsub(and other places too). But note$1=""(with default FS) squashes whitespaces in the command;sub(/^ [0-9]+ /,"")works better onbash historyand I expect something not very different should onzsh. – dave_thompson_085 Nov 21 '15 at 07:35