Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using history expansion in a bash alias or function

Tags:

linux

bash

I am trying to make a simple thing to make my teammates lives easier. They are constantly copying quote into the command line that are formatted which breaks the command ie: “test“ vs. "test"

It's proved surprisingly annoying to do with:

function damn() { !!:gs/“/" }

or:

alias damn='!!:gs/“/"'

Neither seems to work and keeps giving me either the error

-bash: !!:gs/“/" : No such file or directory

or just:

>

I must be missing something obvious here.

like image 520
JSimonsen Avatar asked Feb 09 '18 00:02

JSimonsen


People also ask

What is bash history expansion?

History expansion is performed immediately after a complete line is read, before the shell breaks it into words, and is performed on each line individually. Bash attempts to inform the history expansion functions about quoting still in effect from previous lines. History expansion takes place in two parts.

How do I expand an alias bash script?

Also, Bash aliases are not expanded when your shell isn't interactive unless the expand_aliases shell option is set using shopt -s . You can check your current setting (on or off) by using shopt expand_aliases . instead. Generally, shell functions are preferred over aliases.

Can you use an alias in a bash script?

BASH Alias is a shortcut to run commands using some mapping. It is a way to create some shortcut commands for repetitive and multiple tasks. We create an alias in a BASH environment in specified files. We can also incorporate BASH functions, variables, etc to make the Alias more programmatic and flexible.

What is the purpose of an alias in bash?

A Bash alias is a method of supplementing or overriding Bash commands with new ones. Bash aliases make it easy for users to customize their experience in a POSIX terminal. They are often defined in $HOME/. bashrc or $HOME/bash_aliases (which must be loaded by $HOME/.


2 Answers

! does not work in functions or aliases. According to bash manual:

History expansion is performed immediately after a complete line is read, before the shell breaks it into words.

You can use the builtin fc command:

[STEP 100] # echo $BASH_VERSION
4.4.19(1)-release
[STEP 101] # alias damn='fc -s “=\" ”=\" '
[STEP 102] # echo “test”
“test”
[STEP 103] # damn
echo "test"
test
[STEP 104] #

For quick referecne, the following is output of help fc.

fc: fc [-e ename] [-lnr] [first] [last] or fc -s [OLD=NEW] [command]
    Display or execute commands from the history list.

    fc is used to list or edit and re-execute commands from the history list.
    FIRST and LAST can be numbers specifying the range, or FIRST can be a
    string, which means the most recent command beginning with that
    string.

    Options:
      -e ENAME  select which editor to use.  Default is FCEDIT, then EDITOR,
                then vi
      -l        list lines instead of editing
      -n        omit line numbers when listing
      -r        reverse the order of the lines (newest listed first)

|   With the `fc -s [OLD=NEW ...] [command]' format, COMMAND is
|   re-executed after the substitution OLD=NEW is performed.

    A useful alias to use with this is r='fc -s', so that typing `r cc'
    runs the last command beginning with `cc' and typing `r' re-executes
    the last command.

    Exit Status:
    Returns success or status of executed command; non-zero if an error occurs.
like image 143
pynexj Avatar answered Oct 06 '22 00:10

pynexj


Here is a slightly more general solution using a bash function to wrap the fc call, if you want to do something to the string beyond substitution.

function damn() {
    # Capture the previous command.
    cmd=$(fc -ln -1)

    # Do whatever you want with cmd here
    cmd=$(echo $cmd | sed 's/[“”]/"/g')

    # Re-run the command
    eval $cmd
}
like image 27
merlin2011 Avatar answered Oct 06 '22 00:10

merlin2011