2

Very often, I need to quickly type some lines of characters (for instance for simplifying a mathematical expression) and then discard the whole stuff. Of course, I generally have several running sessions of my text editor, and I can do it there. I have also been using the following system; I type echo " in a terminal (running bash) and then type anything; when I am done, I type a closing ".

Yesterday, I decided to add something more elegant in my .bashrc and I created the following alias:

# write junk on the terminal (stop with a line containing only "." )
# alias scratch="awk '/^\.$/{exit}'"
# alias scratch="sed -ne '/^\.$/q'"
alias scratch='grep -q "^\.$"'

You can see above three variants doing the same thing: I type scratch, then type whatever I want to type, and I end with a line containing only . (dot).

I am very happy with that, but I also thought at the following variant:

alias scratch="cat - > /dev/null << ."

which does the same thing with an initial prompt > at the beginning of each line.

Then, I wondered how I could use the PS2 environment variable for changing this prompt, and I couldn't get anything fully working. Of course, the current PS2 prompt should be restored when I am done. How can I set the prompt for this variant of my scratch alias to any arbitrary string during the time of the "scratch" session only?

1
  • Not an answer to your question, but I use something like cat > /dev/null all the time; you could alias scratch='cat > /dev/null' and end with a Control-D or Control-C.
    – Jeff Schaller
    Jun 10, 2019 at 14:53

2 Answers 2

1

I'm not entirely sure what this is useful for (compared to nano, vim or any editor you fancy), but... does it need an alias?

$ <<.
> foo
> bar
> baz
> .

Just " would be even shorter but there'll be an error message...

$ "
> oh
> ah
> ui
> "
bash: $'\noh\nah\nui\n': command not found

Note that these things are not really gone...

$ history
  497  <<.
foo
bar
baz
.

If that bothers you, disable history first or clear it afterwards.

For a custom PS2 prompt, it's difficult since (at least for Bash) it has to be set to the parent shell. If you set it in a subshell, it'll be ignored. You can kind of work around it by starting an explicit shell instance like this...

$ PS1=@_ PS2=:_ bash --norc
@_<<.
:_hey
:_.
@_exit
$

But at this point it would make more sense to write a dedicated scratch and discard program.

Different approach, not using the PS2 prompt at all:

$ while read -p ":-> " ; do : ; done
:-> hey
:-> how 
:-> do

Only you can't use '.' to get out here. Well, you could easily add that as a condition...

$ alias scratch='(var=_; while read -r -p ":-> " var; do [ "$var" == . ] && break; done)'
$ scratch
:-> a
:-> b
:-> c
:-> .

However, you can also just get out by sending EOF with Ctrl+D.

1
  • Thank you for the <<. idea; it is even shorter to type than my current alias! Jun 10, 2019 at 15:17
1

Use read to read input line by line. You can specify a prompt. The following snippet reads lines and ignores their content until a line consisting of optional whitespace around a single dot, or until you press Ctrl+D on a blank line.

scratch () {
  local line
  while [[ "$line" != "." ]] && read -r -e -p "scratch> " line; do :; done
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .