The availability of the % string only after a command unrelated to it (not using !??) is executed as shown below is not documented, but it probably falls under the category of a bug. That is, it seems reasonable that both echo "!%" commands should behave as the second one does. [root@localhost ~]# bash [root@localhost ~]# echo "!%" bash: !: event not found [root@localhost ~]# echo a >/dev/nul [root@localhost ~]# echo "!%" echo ""
[root@localhost ~]# Jim On Mon, Nov 4, 2019 at 9:42 AM Jim Monte <jim.mont...@gmail.com> wrote: > Related to the issues with the ? event designator, the %word designator > substitutes the *first* word matched by the ? event designator or nothing > if the match begins with a space. These details are not documented. > > [root@localhost ~]# echo a b c d >/dev/nul > [root@localhost ~]# echo !?b c? > echo echo a b c d >/dev/nul > [root@localhost ~]# echo "!%" > echo "b" > b > [root@localhost ~]# echo a1 >/dev/nul > [root@localhost ~]# echo !? a? > echo echo a1 >/dev/nul > [root@localhost ~]# echo "!%" > echo "" > > Jim > > > > > > On Sun, Nov 3, 2019 at 9:18 AM Jim Monte <jim.mont...@gmail.com> wrote: > >> Two more documentation issues I have found are below. >> >> It appears that an empty substring event designator uses the string of >> the previous substring event designator if none is provided and does not >> find the event if there is no previous string. >> >> [root@localhost ~]# ls >> dos hello.c >> [root@localhost ~]# cat hello.c > /dev/nul >> [root@localhost ~]# echo !?s? >> echo ls >> ls >> [root@localhost ~]# echo !?? >> echo echo ls >> echo ls >> [root@localhost ~]# ls -al > /dev/nul >> [root@localhost ~]# echo !?? >> echo ls -al > /dev/nul >> [root@localhost ~]# echo s >> s >> [root@localhost ~]# echo !?? >> echo echo s >> echo s >> [root@localhost ~]# echo !?l? >> echo echo ls -al > /dev/nul >> [root@localhost ~]# echo !?? >> echo echo echo ls -al > /dev/nul >> >> [root@localhost ~]# bash >> [root@localhost ~]# echo !?? >> bash: !??: event not found >> >> This action is not documented. >> >> >> >> >> >> An empty "old" string in a substitute word modifier uses the previous >> "old" if none is given, but uses an empty string if new is empty. If there >> was no previous "old" string, an error is reported. >> >> [root@localhost ~]# echo f g i >> f g i >> [root@localhost ~]# echo !:s/g/k/ >> echo echo f k i >> echo f k i >> [root@localhost ~]# echo af ag ai >> af ag ai >> [root@localhost ~]# echo !:s/// >> echo echo af a ai >> echo af a ai >> [root@localhost ~]# echo bf bg bi >> bf bg bi >> [root@localhost ~]# echo !:s//1/ >> echo echo bf b1 bi >> echo bf b1 bi >> [root@localhost ~]# echo gf gg gi >> gf gg gi >> [root@localhost ~]# echo !:gs//2/ >> echo echo 2f 22 2i >> echo 2f 22 2i >> >> [root@localhost ~]# bash >> [root@localhost ~]# echo a b c >> a b c >> [root@localhost ~]# echo !:s//1/ >> bash: :s//1/: no previous substitution >> >> Again, this behavior is not documented. >> >> On Thu, Oct 10, 2019 at 10:35 PM Jim Monte <jim.mont...@gmail.com> wrote: >> >>> Hi, >>> >>> This bug report has been my first one for Bash. I have not found how to >>> check the status of the bug. Would you please provide this information? >>> >>> Below are a couple more issues I found. >>> >>> There is an inconsistency with the documentation and behavior of the ^ >>> word designator. According to documentation, it refers to the first >>> argument but does not require a ':' before it if it starts the word >>> designator. However, it does not act like the numerical word designator 1 >>> at the end of a range. >>> >>> [root@localhost ~]# echo a b c >>> a b c >>> [root@localhost ~]# echo !!:1-1 >>> echo a >>> a >>> [root@localhost ~]# echo a b c >>> a b c >>> [root@localhost ~]# echo !!:^-^ >>> echo a b^ >>> a b^ >>> >>> Also it is not explicitly documented that :- is equivalent to :0- >>> >>> [root@localhost ~]# echo a b c d >>> a b c d >>> [root@localhost ~]# echo !!:- >>> echo echo a b c >>> echo a b c >>> [root@localhost ~]# echo a b c d >>> a b c d >>> [root@localhost ~]# echo !!:0- >>> echo echo a b c >>> echo a b c >>> >>> >>> Jim Monte >>> >>> On Thu, Oct 3, 2019 at 6:19 PM Jim Monte <jim.mont...@gmail.com> wrote: >>> >>>> Hi All, >>>> >>>> Below are some issues I found with history substitution. I am >>>> duplicating its behavior in a somewhat different use, and found issues with >>>> the documentation and bugs as described. >>>> >>>> Jim Monte >>>> >>>> >>>> >>>> >>>> From: jim >>>> To: bug-bash@gnu.org >>>> Subject: Issues with history substitution and its documentation >>>> >>>> Configuration Information [Automatically generated, do not change]: >>>> Machine: x86_64 >>>> OS: linux-gnu >>>> Compiler: gcc >>>> Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' >>>> -DCONF_OSTYPE='l$ >>>> uname output: Linux T5500-Ubuntu 4.18.0-22-generic #23~18.04.1-Ubuntu >>>> SMP Thu J$ >>>> Machine Type: x86_64-pc-linux-gnu >>>> >>>> Bash Version: 4.4 >>>> Patch Level: 19 >>>> Release Status: release >>>> >>>> Description: >>>> >>>> ============================================================================= >>>> Documentation of quick substitution is incorrect (or does not match >>>> behavior). >>>> >>>> I believe this issue is an error with the documentation of history >>>> "Quick Substitution" that has existed since the first snapshot >>>> available at >>>> web.archive.org in 2007 at >>>> >>>> >>>> https://web.archive.org/web/20071223174140/http://www.gnu.org/software/bash/manual/html_node/Event-Designators.html >>>> >>>> At the least it is true that bash does not behave as the documentation >>>> states, >>>> but it does act in a way that is more reasonable (to me) than what is >>>> written. >>>> >>>> The documentation states that ^string1^string2^ is equivalent to >>>> !!:s/string1/string2/. However, bash treats it as equivalent to >>>> !!:s^string1^string2^. >>>> >>>> jim@T5500-Ubuntu:~$ echo /a >>>> /a >>>> jim@T5500-Ubuntu:~$ ^/a^b^ >>>> echo b >>>> b >>>> jim@T5500-Ubuntu:~$ echo /a >>>> /a >>>> jim@T5500-Ubuntu:~$ !!:s//a/b/ >>>> echo ab/ >>>> ab/ >>>> jim@T5500-Ubuntu:~$ echo /a >>>> /a >>>> jim@T5500-Ubuntu:~$ !!:s^/a^b^ >>>> echo b >>>> b >>>> >>>> >>>> ============================================================================= >>>> Behavior of empty "old" string in a substitution is undefined. >>>> >>>> The earlier example also shows a related but different issue with the >>>> !!:s//a/b/ command, where the string to locate is empty. >>>> It causes /a to be replaced by a and the b/ is appended. >>>> >>>> But >>>> jim@T5500-Ubuntu:~$ echo ///a >>>> ///a >>>> jim@T5500-Ubuntu:~$ !!:s//z/ >>>> echo //z >>>> //z >>>> >>>> Here the empty string caused /a to be replaced by z. >>>> >>>> However, >>>> jim@T5500-Ubuntu:~$ echo ///abcdefg >>>> ///abcdefg >>>> jim@T5500-Ubuntu:~$ !!:s//z/ >>>> echo //zbcdefg >>>> //zbcdefg >>>> >>>> Here a slash and the first character of the second word are replaced by >>>> z. >>>> >>>> >>>> jim@T5500-Ubuntu:~$ echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ !!:s//z/ >>>> echo z b c >>>> z b c >>>> >>>> >>>> jim@T5500-Ubuntu:~$ echo /// >>>> /// >>>> jim@T5500-Ubuntu:~$ !!:s//z/ >>>> bash: :s//z/: substitution failed >>>> >>>> Using :gs instead of :s does not change the results. >>>> >>>> >>>> ============================================================================= >>>> BUG >>>> If an event designator has a leading - character, it is ignored. >>>> >>>> jim@T5500-Ubuntu:~/tmp$ cat main.c >>>> #include <stdio.h> >>>> int main(void) >>>> { >>>> (void) fprintf(stdout, "Hello, world!\n"); >>>> return 0; >>>> } >>>> >>>> jim@T5500-Ubuntu:~/tmp$ gcc main.c -o"-a" >>>> jim@T5500-Ubuntu:~/tmp$ gcc main.c -o"-b" >>>> jim@T5500-Ubuntu:~/tmp$ -a >>>> Hello, world! >>>> jim@T5500-Ubuntu:~/tmp$ !-a:s/a/b >>>> bpt-cache abc >>>> >>>> >>>> >>>> ============================================================================= >>>> Documentation of the :h and :t modifiers in section 9.3.3 is incomplete. >>>> :h removes the last / and everything after it if a / is present. >>>> Otherwise >>>> it does nothing. >>>> >>>> :t removes everything before and including the last / if one is present. >>>> Otherwise it does nothing. >>>> >>>> If a slash is present, !!:h/!!:t is equivalent to !!. >>>> >>>> jim@T5500-Ubuntu:~$ echo /a/b/c/d >>>> /a/b/c/d >>>> jim@T5500-Ubuntu:~$ !!:h >>>> echo /a/b/c >>>> /a/b/c >>>> jim@T5500-Ubuntu:~$ echo /a/b/c/d >>>> /a/b/c/d >>>> jim@T5500-Ubuntu:~$ !!:h:h >>>> echo /a/b >>>> /a/b >>>> jim@T5500-Ubuntu:~$ echo /a/b/c/d >>>> /a/b/c/d >>>> jim@T5500-Ubuntu:~$ !!:h:h:h >>>> echo /a >>>> /a >>>> jim@T5500-Ubuntu:~$ echo /a/b/c/d >>>> /a/b/c/d >>>> jim@T5500-Ubuntu:~$ !!:h:h:h:h >>>> echo >>>> >>>> jim@T5500-Ubuntu:~$ >>>> jim@T5500-Ubuntu:~$ echo /a/b/c/d >>>> /a/b/c/d >>>> jim@T5500-Ubuntu:~$ !!:t >>>> d >>>> d: command not found >>>> >>>> >>>> jim@T5500-Ubuntu:~$ echo a/b >>>> a/b >>>> jim@T5500-Ubuntu:~$ !!:h/!!:t >>>> echo a/b >>>> a/b >>>> jim@T5500-Ubuntu:~$ echo a/b >>>> a/b >>>> jim@T5500-Ubuntu:~$ !! >>>> echo a/b >>>> a/b >>>> >>>> >>>> >>>> ============================================================================= >>>> Documentation of the :r and :e modifiers is incomplete. >>>> :r removes the last ".suffix" and everything after it, if a ".suffix" is >>>> present. Otherwise it does nothing. >>>> :e leaves the last ".suffix" and everything after it, if a ".suffix" is >>>> present. Otherwise it does nothing. >>>> >>>> jim@T5500-Ubuntu:~$ echo .suffix a b .suffix c d >>>> .suffix a b .suffix c d >>>> jim@T5500-Ubuntu:~$ !!:r >>>> echo .suffix a b >>>> .suffix a b >>>> jim@T5500-Ubuntu:~$ echo .suffix a b .suffix c d >>>> .suffix a b .suffix c d >>>> jim@T5500-Ubuntu:~$ !!:r:r >>>> echo >>>> >>>> jim@T5500-Ubuntu:~$ echo .suffix a b .suffix c d >>>> .suffix a b .suffix c d >>>> jim@T5500-Ubuntu:~$ !!:e >>>> .suffix c d >>>> >>>> jim@T5500-Ubuntu:~$ echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ !!:r >>>> echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ !!:e >>>> echo a b c >>>> a b c >>>> >>>> >>>> ============================================================================= >>>> BUG >>>> :p does not suppress execution if it is duplicated. >>>> >>>> jim@T5500-Ubuntu:~$ echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ !!:p >>>> echo a b c >>>> jim@T5500-Ubuntu:~$ echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ !!:p:p >>>> echo a b c >>>> a b c >>>> >>>> >>>> ============================================================================= >>>> Documentation of :q and :x is incomplete. >>>> If :q and :x are repeated, the last specification is taken. >>>> >>>> jim@T5500-Ubuntu:~$ echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ !!:q >>>> 'echo a b c' >>>> echo a b c: command not found >>>> jim@T5500-Ubuntu:~$ echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ !!:x >>>> 'echo' 'a' 'b' 'c' >>>> a b c >>>> jim@T5500-Ubuntu:~$ echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ !!:q:x >>>> 'echo' 'a' 'b' 'c' >>>> a b c >>>> jim@T5500-Ubuntu:~$ echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ !!:q:x:q >>>> 'echo a b c' >>>> echo a b c: command not found >>>> jim@T5500-Ubuntu:~$ echo a b c >>>> a b c >>>> jim@T5500-Ubuntu:~$ !!:q:x:q:x >>>> 'echo' 'a' 'b' 'c' >>>> a b c >>>> >>>> >>>> >>>> ============================================================================= >>>> Finally, documentation of G should mention that it can be used with >>>> both :s and &. >>>> >>>> >>>>