sed 's/\\\\/& /g;s/\\n/\
/g; s/\\\\ /\\\\/g' <in >out
...should handle the \n
ewline 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 \n
ewline 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 \n
ewlines 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\n
is coming fromawk
? – Tom Zych Nov 21 '15 at 02:34sed
orgsed
... it has to do with the shell you are using and the expansion of"\n"
. Try the final-e
option to sed as-e 's/\\n/\n/g'
(theg
will 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-e
expression that's failing. The rest is just for context. Instead of a newline, I'm getting ann
as 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\n
ewline character into the substitution. – mikeserv Nov 21 '15 at 03:14awk
which you are using anyway portably (POSIXly) supports\n
and 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 history
and I expect something not very different should onzsh
. – dave_thompson_085 Nov 21 '15 at 07:35