/ / Drukuj funkcje środowiska powłoki w pojedynczej linii - bash, shell, awk, sed

Drukuj funkcje środowiska powłoki w pojedynczej linii - bash, shell, awk, sed

W bashu, działa set wyświetli wszystkie ustawienia środowiska. Chcę wyświetlać moje funkcje jako pojedynczą linię dla każdej funkcji. Więc zamiast biegać set i otrzymanie tego (na przykład):

gcm ()
{
git commit -m "$@";
git --no-pager log -1 | grep --color ^commit
}
gcma ()
{
git commit -a -m "$@";
git --no-pager log -1 | grep --color ^commit
}

Ja chcę to zobaczyć:

gcm () { git commit -m "$@"; git --no-pager log -1 | grep --color ^commit }
gcma () { git commit -a -m "$@"; git --no-pager log -1 | grep --color ^commit }

Tak myślę, że chcę polecenie sed / awk, które będzie szukać regex " ()$" i łącz się z każdą kolejną linią (znakiem odstępu), aż do wyrażeń regularnych "^}$" jest dopasowany, a cokolwiek innego powinno po prostu wydrukować tak jak jest.

AKTUALIZACJA: Wszystkie dotychczas przesłane przykłady pobierają wszystkie dane wejściowe i renderują je w jednym wierszu, a to nie jest dokładnie w porządku. Chcę, aby każda funkcja (zestaw " ()$" do "^}$", włącznie) jako pojedyncza linia.

Odpowiedzi:

2 dla odpowiedzi № 1

Mały scenariusz

Spróbuj tego:

declare -f gcm gcma dequote quote |
sed "1h;1!H;/^}$/!d;s/.//;x;s/n[ o11]*//g;s/}$/;}/"

może renderować:

gcm () { git commit -m "$@";git --no-pager log -1 | grep --color ^commit;}
gcma () { git commit -a -m "$@";git --no-pager log -1 | grep --color ^commit;}
quote () { local quoted=${1//"/"\""};printf ""%s"" "$quoted";}
dequote () { eval printf %s "$1" 2> /dev/null;}

Dodałem pół kolumny, aby móc znaleźć wyjście.

Silniejszy

Ta wersja przeanalizuje wyjście z set polecenie bez argumentów i podjęcia wszystko, ale tylko Funkcje:

set | sed "/^[a-z0-9A-Z_.-]+ () *$/,/^}$/{ //{ /()/{h;d;}};H ;/^}$/!d;g;s/n[ o11]*//g;s/}$/;}/;p;};d"

Może to być napisane:

set | sed "
/^[a-z0-9A-Z_.-]+ () *$/,/^}$/{
//{
/()/ {
h;
d;
};
};
H;
/^}$/!d;
g;
s/n[ o11]*//g;
s/}$/;}/;
p;
};
d;
"

Uwaga: [a-z0-9A-Z_.-]+ nie jest dobrze sprawdzony: nie jestem całkowicie pewien, co może zawierać nazwa funkcji.

Szczegółowe wyjaśnienie

Istnieje runnable skrypt z wyjaśnieniem wiersz po wierszu

#!/bin/sed -nf
# -n modifier won"t output anything without explicit "p" command

/^[a-z0-9A-Z_.-]+ () *$/ , /^}$/ { # from lines beginning by funcname, to ^}$
//{                # At first or last line of block...
/()/{          # If containing "()",
h;         # place this line in hold space,
d;         # then delete (go to next line)
};
};
H;                 # Append to hold space
/^}$/!d;           # If not "^}$", delete this line (go to next line)
g;                 # replace current line by hold space
s/n[ o11]*//g;   # Suppress each new line and following spaces or tabs
s/}$/;}/;          # Add semi-colon before last "}" in order to source
p;                 # print
}

Skopiuj to do pliku, do którego możesz zadzwonić bashFuncToOneLine.sed następnie chmod +x spacebashFuncToOneLine.sed

declare -f gcm{,a}  | ./bashFuncToOneLine.sed
gcm () { git commit -m "$@";git --no-pager log -1 | grep --color ^commit;}
gcma () { git commit -a -m "$@";git --no-pager log -1 | grep --color ^commit;}

set | ./bashFuncToOneLine.sed | less -S

1 dla odpowiedzi nr 2

W awk:

$ awk "sub(/}/,"}n")||$1=$1" ORS="" file

lub usuń file i rura do niego (w takim przypadku musisz awk -v ORS=""...). Wynik:

gcm (){git commit -m "$@";git --no-pager log -1 | grep --color ^commit}
gcma (){git commit -a -m "$@";git --no-pager log -1 | grep --color ^commit}
  • zastąpić } z }n
  • I użyć ORS="" aby usunąć (inne niż wyżej) nowe linie
  • i $1=$1 aby odbudować rekordy, aby przyciąć przestrzeń

0 dla odpowiedzi № 3

Spróbuj tego -

awk  "{gsub(/[[:space:]]+/," ") ;ORS=(/}/?RS:FS)}1" f
gcm () {  git commit -m "$@";  git --no-pager log -1 | grep --color ^commit }
gcma () {  git commit -a -m "$@";  git --no-pager log -1 | grep --color ^commit }