Skript som gör alias av senaste kommando…

Här diskuterar vi skal, kommandon och klassiska linuxverktyg.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Skript som gör alias av senaste kommando…

Inlägg av Johnny Rosenberg »

Hade en idé om att göra ett enkelt skript (bash) som gör följande:
Plockar fram senaste kommandot (eller näst senaste, eftersom det senaste förmodligen är körandet av själva skriptet) från ~/.bash_history, gör ett alias av det och placerar alias-kommandot sist i filen ~/.bash-aliases – en fil som jag anropar från ~/.bashrc.

Men jag stötte på patrull efter patrull.

Först upptäckte jag att kommandot history inte funkar i ett skript; det returnerar ingenting då.
Okej, inga problem, jag tittar istället direkt i ~/.bash_history. Nehej, det gick inte, för den är sällan aktuell; det fattas oftast några tiotal rader där, så det verkar som att den samlar på sig kommandon och lägger in dem klumpvis i filen.
Men okej, det gick tydligen att åtgärda genom att skriva några väl valda rader i sin ~/.bashrc-fil, men det känns ju lite ”så där” att man ska behöva ha sitt system specialkonfigurerat för att ett visst skript ska fungera.

Så fick jag en annan idé, nämligen att användaren själv kan mata in senaste kommandot som argument till skriptet. Låter ju jobbigt, men det är ju väldigt enkelt tack vare ”!!” som ju expanderas till senaste kommandot automatiskt.

Jaha ja, vad bra, då. Så jag börjar skriva på lite i all min okunnighet, men stöter åter på patrull.

Lättast att visa med ett exempel.
Jag kanske vill göra ett alias för att ta mig till en speciell mapp som ligger ett antal nivåer neråt. Manuellt kanske man skriver:
cd "/home/jag/min fina/mapp som tar/en stund/att/skriva/sökvägen till"
Man kan givetvis också skriva:
cd /home/jag/min\ fina/mapp\ som\ tar/en\ stund/att/skriva/sökvägen\ till

Problemet är ju att om man väljer första skrivsättet så förvinner citat-tecknen och om man väljer andra skrivsättet så försvinner bakåtsnedstrecken när väl texten tagits in till skriptet i form av argument eller parametrar eller vad man kallar det!

Jag kom inte på något enkelt sätt att komma runt detta, i alla fall inte om användaren ska förväntas kunna mata in i princip vad som helst.
Är det bara ”cd sökväg” som väntas är det ju enkelt att låta skriptet ”manuellt” placera ut dubbelfnuttarna på rätt ställen, men det är kanske inte så ofta som det är så enkelt.

Någon som har några idéer?

Så här hade jag tänk mig att det hela skulle fungera:
Användaren kör ett kommando och kommer på att han vill ha det som ett alias, eftersom han kommer att utföra det ganska ofta. Det kan vara vad som helst, men låt oss hålla oss till det enkla:
cd "/home/jag/min fina/mapp som tar/en stund/att/skriva/sökvägen till"

Ett skript som heter ”pa” (permanent alias…) ska fixa biffen om man kör det direkt efter föregående kommando:
pa xyz !!

Bash expanderar detta till:
pa xyz cd "/home/jag/min fina/mapp som tar/en stund/att/skriva/sökvägen till"

Skriptet ska sedan sätta ihop detta till ett alias-kommando:
alias xyz='cd "/home/jag/min fina/mapp som tar/en stund/att/skriva/sökvägen till"' som sedan ska läggas på slutet av ~/.bash-aliases, så att aliaset kommer att fungera permanent.

Istället blir det:
alias xyz='cd /home/jag/min fina/mapp som tar/en stund/att/skriva/sökvägen till'
vilket inte leder längre än till ett felmeddelande, eftersom mellanslagen tjänstgör som separator mellan parametrar till cd-kommandot.

Någon som kommer på något enkelt sätt att komma runt detta lilla mini-problem? Förutom att användaren själv skriver ”\\” istället för ”\” eller ”\"” istället för ”"”, förstås…

Visst kan man analysera varje ord och lista ut vad som är sökvägar och inte, men det känns som ett lite större projekt än vad jag hade tänkt mig, vilket enbart kommer att resultera i att det rinner ut i sanden.

Funderar också på om det blir annorlunda om jag väljer att göra det i C istället (mest på grund av att jag inte kan något annat, och knappt det ens), men jag misstänker att det inte spelar någon roll.

Som sagt, idéer är välkomna.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
mcNisse
Inlägg: 5211
Blev medlem: 06 feb 2007, 20:51
OS: Debian
Utgåva: Vet inte/ingen utgåva passar

Re: Skript som gör alias av senaste kommando…

Inlägg av mcNisse »

Du kan köra pa med "!!" så får du hela uttrycket som ett argument istället för flera (i bästa fall, se exemplet). Det gör att skriptet fungerar med \. Dock inte när man använder fnuttar.

Kod: Markera allt

pa() {
echo "alias $1='$2'"
}
#backslash
echo hej\ hopp
pa hp "!!"
==>
pa hp "echo hej\ hopp"
alias hp='echo hej\ hopp
#fnuttar
echo "hej hopp"
pa hp "!!"
==>
pa hp "echo "hej hopp""
alias hp='echo hej'
Som du ser kvaddas funtionaliteten av fnuttar. Då blir det inte längre ett argument utan flera.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Skript som gör alias av senaste kommando…

Inlägg av Johnny Rosenberg »

mcNisse skrev:Du kan köra pa med "!!" så får du hela uttrycket som ett argument istället för flera (i bästa fall, se exemplet). Det gör att skriptet fungerar med \. Dock inte när man använder fnuttar.

Kod: Markera allt

pa() {
echo "alias $1='$2'"
}
#backslash
echo hej\ hopp
pa hp "!!"
==>
pa hp "echo hej\ hopp"
alias hp='echo hej\ hopp
#fnuttar
echo "hej hopp"
pa hp "!!"
==>
pa hp "echo "hej hopp""
alias hp='echo hej'
Som du ser kvaddas funtionaliteten av fnuttar. Då blir det inte längre ett argument utan flera.
Okej, det är ju ett sätt att komma runt det hela lite med bara två extra tangentnedtryckningar. Får väl anses vara acceptabelt.

Funderar på om det kunde fungera med enkelfnuttar?
pa hp '!!'
Ska strax åka till jobbet så jag hinner inte testa nu.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: Skript som gör alias av senaste kommando…

Inlägg av Konservburk »

Johnny Rosenberg skrev:Hade en idé om att göra ett enkelt skript (bash) som gör följande:
Plockar fram senaste kommandot (eller näst senaste, eftersom det senaste förmodligen är körandet av själva skriptet) från ~/.bash_history,
Det är inte lämpligt att använda ~/.bash_history för sånt här eftersom den inte alltid är helt uppdaterad. Det kan dessutom uppstå konflikter om du har flera olika terminaler igång samtidigt. Då är det bättre att använda den interna historielistan istället (se help history för mer info).
Johnny Rosenberg skrev:gör ett alias av det och placerar alias-kommandot sist i filen ~/.bash-aliases – en fil som jag anropar från ~/.bashrc.
Det är faktiskt inte möjligt att göra alias av allt som kan tänkas finnas i historielistan. Då är det bättre att använda skalfunktioner så undviker du smidigt alla de begränsningar som alias har.
Johnny Rosenberg skrev:Men jag stötte på patrull efter patrull.

Först upptäckte jag att kommandot history inte funkar i ett skript; det returnerar ingenting då.
Du bör inte använda dig av ett separat skript i det här fallet. Använd en skalfunktion istället så kommer du enkelt åt historielistan. Om du av någon anledning verkligen vill ha ett separat skript så måste du läsa in det med kommandot source istället för att köra det som vanligt.
Johnny Rosenberg skrev:Någon som har några idéer?

Så här hade jag tänk mig att det hela skulle fungera:
Användaren kör ett kommando och kommer på att han vill ha det som ett alias, eftersom han kommer att utföra det ganska ofta. Det kan vara vad som helst, men låt oss hålla oss till det enkla:
cd "/home/jag/min fina/mapp som tar/en stund/att/skriva/sökvägen till"

Ett skript som heter ”pa” (permanent alias…) ska fixa biffen om man kör det direkt efter föregående kommando:
pa xyz !!

Bash expanderar detta till:
pa xyz cd "/home/jag/min fina/mapp som tar/en stund/att/skriva/sökvägen till"

Skriptet ska sedan sätta ihop detta till ett alias-kommando:
alias xyz='cd "/home/jag/min fina/mapp som tar/en stund/att/skriva/sökvägen till"' som sedan ska läggas på slutet av ~/.bash-aliases, så att aliaset kommer att fungera permanent.
Mitt förslag är som sagt att du använder skalfunktioner istället för skript och alias. Det skulle kunna se ut ungefär så här:

Kod: Markera allt

pa(){
   eval function $(printf '%q(){' "$1") "$(fc -ln -1 && echo \})" &&
   declare -f "$1" | tee -a ~/.bash-aliases
}
Lägg in detta i ~/.bashrc (eller motsvarande). Då kan du köra pa xyz för att automatiskt skapa en skalfunktion xyz av kommandot som kördes i samma terminal precis innan (som hamnar i slutet av ~/.bash-aliases).

Jag tyckte att det kunde vara vettigt att få se vad som just har lagts till. Om du inte vill ha sådan utdata så kan du byta ut
| tee -a mot >> istället.
Användarvisningsbild
mcNisse
Inlägg: 5211
Blev medlem: 06 feb 2007, 20:51
OS: Debian
Utgåva: Vet inte/ingen utgåva passar

Re: Skript som gör alias av senaste kommando…

Inlägg av mcNisse »

Konservburk skrev:Mitt förslag är som sagt att du använder skalfunktioner istället för skript och alias. Det skulle kunna se ut ungefär så här:

Kod: Markera allt

pa(){   eval function $(printf '%q(){' "$1") "$(fc -ln -1 && echo \})" &&   declare -f "$1" | tee -a ~/.bash-aliases}
Snyggt och lärorikt!!! fc och declare kände jag inte till.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Skript som gör alias av senaste kommando…

Inlägg av Johnny Rosenberg »

Konservburk skrev:Det skulle kunna se ut ungefär så här:

Kod: Markera allt

pa(){
   eval function $(printf '%q(){' "$1") "$(fc -ln -1 && echo \})" &&
   declare -f "$1" | tee -a ~/.bash-aliases
}
Lägg in detta i ~/.bashrc (eller motsvarande). Då kan du köra pa xyz för att automatiskt skapa en skalfunktion xyz av kommandot som kördes i samma terminal precis innan (som hamnar i slutet av ~/.bash-aliases).

Jag tyckte att det kunde vara vettigt att få se vad som just har lagts till. Om du inte vill ha sådan utdata så kan du byta ut
| tee -a mot >> istället.
Jisses – jag trodde mitt problem var i det närmaste omöjligt att lösa. Är övertygad om att jag aldrig hade kunnat få ett sådant här svar från Ubuntu-mail-listan. Imponerande.
Idag lärde jag mig något nytt, tackar för det!
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Skriv svar

Återgå till "Terminalforum"