Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
849 views
in Technique[技术] by (71.8m points)

bash - Detect empty command

Consider this PS1

PS1='
${_:+$? }$ '

Here is the result of a few commands

$ [ 2 = 2 ]

0 $ [ 2 = 3 ]

1 $

1 $

The first line shows no status as expected, and the next two lines show the correct exit code. However on line 3 only Enter was pressed, so I would like the status to go away, like line 1. How can I do this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here's a funny, very simple possibility: it uses the # escape sequence of PS1 together with parameter expansions (and the way Bash expands its prompt).

The escape sequence # expands to the command number of the command to be executed. This is incremented each time a command has actually been executed. Try it:

$ PS1='# $ '
2 $ echo hello
hello
3 $ # this is a comment
3 $
3 $    echo hello
hello
4 $

Now, each time a prompt is to be displayed, Bash first expands the escape sequences found in PS1, then (provided the shell option promptvars is set, which is the default), this string is expanded via parameter expansion, command substitution, arithmetic expansion, and quote removal.

The trick is then to have an array that will have the k-th field set (to the empty string) whenever the (k-1)-th command is executed. Then, using appropriate parameter expansions, we'll be able to detect when these fields are set and to display the return code of the previous command if the field isn't set. If you want to call this array __cmdnbary, just do:

PS1='
${__cmdnbary[#]-$? }${__cmdnbary[#]=}$ '

Look:

$ PS1='
${__cmdnbary[#]-$? }${__cmdnbary[#]=}$ '

0 $ [ 2 = 3 ]

1 $ 

$ # it seems that it works

$     echo "it works"
it works

0 $

To qualify for the shortest answer challenge:

PS1='
${a[#]-$? }${a[#]=}$ '

that's 31 characters.

Don't use this, of course, as a is a too trivial name; also, $ might be better than $.


Seems you don't like that the initial prompt is 0 $; you can very easily modify this by initializing the array __cmdnbary appropriately: you'll put this somewhere in your configuration file:

__cmdnbary=( '' '' ) # Initialize the field 1!
PS1='
${__cmdnbary[#]-$? }${__cmdnbary[#]=}$ '

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...