AWK: symulacja polecenia dirname

Opublikował siefca wt 21 paź 2008 10:30:08 GMT

W systemach typu Unix istnieje polecenie o nazwie dirname, którego zadaniem jest wyświetlenie podanej nazwy ścieżkowej skróconej przez oddzielenie ostatniego elementu znajdującego się po wysuniętym najbardziej na prawo znaku ukośnika (włączając ukośnik). Wykorzystuje się je do tego, aby na podstawie ścieżki określającej nazwę pliku uzyskać nazwę katalogu. Czasami też wykorzystywane bywa w skryptach, które rekurencyjnie wywołując dirname dla tej samej zmiennej “podróżują” w głąb drzewa katalogowego. Ostatnimi czasy musiałem posłużyć się wielokrotnie wywoływanym poleceniem dirname w połączeniu ze skryptem awk. Tak więc, chcąc uniknąć zbędnego powoływania do życia osobnego procesu, a tym samym spowalniania wykonywania skryptu, pokusiłem się o stworzenie implementacji dirname w awk.

Składnia C

char *dirname(char *ścieżka);

Opis

Na podstawie podanej nazwy ścieżki funkcja dirname() tworzy łańcuch znaków będący ścieżką, która została skrócona przez usunięcie ostatniego (licząc od lewej do prawej) znaku ukośnika wraz z tym znakiem. Do oddzielenia ostatniego członu nazwy używana jest tablica łańcuchów. Dodatkowo, powtórzone więcej niż raz i znajdujące się obok siebie znaki ukośnika, które są separatorami poszczególnych poziomów drzewa katalogowego, są usuwane.

Funkcja nie operuje na systemie plików – wszelkie operacje dokonywane są wyłącznie na przekazanym łańcuchu znaków.

Zwracana wartość

Funkcja zwraca łańcuch tekstowy, który jest ścieżką reprezentującą nadrzędny poziom w drzewie katalogowym względem podanej ścieżki. W przypadku podania nazwy znajdującej się w katalogu bieżącym, której nie da się już bardziej skrócić zwracana jest nazwa reprezentująca katalog bieżący, czyli pojedynczy znak kropki (.). Taki sam wynik da wykonanie funkcji, gdy jako parametr przekazany zostanie łańcuch złożony z dwóch kropek (..) oznaczający katalog względnie nadrzędny.

Zgodność

  • awk
  • gawk
  • dirname

Kod funkcji

# dirname in awk (using arrays)
#
    function dirname(dir) {
            arylen = split(dir, ary, /\/+/);
            if (ary[arylen] == "") arylen--;
            if (arylen <= 2) {
                if (ary[1] == "") return "/";
                else return ".";
            }
            name = "";
            for (i=1; i <= arylen-1; i++)
                name = name (i==1?"":"/") ary[i];
            return name;
        }

Inne warianty

Tę samą funkcję skracania ścieżki można zaprogramować na wiele sposobów. Posłużyłem się tablicami i pętlami, ponieważ są to operacje mniej czasochłonne niż popularnie wykorzystywane wyrażenia regularne; szczególnie, gdy w celu zapewnienia zgodności z oryginalnym poleceniem trzeba tworzyć wyjątki.

To jest wariant tej funkcji wykorzystujący wyrażenia regularne:

# dirname in awk (using regexps)
#
  function dirname(dir) {
        gsub(/\/+/, "/", dir);
        sub(/\/$/, "", dir);
        if (dir=="." || dir==".." || dir!~/\//)
            return ".";
        else {
            mark=0;
            if (substr(dir,1,1)=="/") mark=1;
            sub(/\/[^\/]*$/, "", dir);
            if (mark==1 && dir=="") dir="/";
            return dir;
        }
    } 

A tu są czasy wykonywania obu funkcji dla 2048 iteracji:

 real    0m3.056s  # tablice (arrays)
 user    0m0.596s
 sys     0m1.796s

 real    0m3.552s # wyrażenia regularne (regexps)
 user    0m1.576s
 sys     0m2.260s

Z oczywistych względów wybrałem funkcję wykorzystującą tablice.

Uwagi

Przedstawione powyżej funkcje możesz uruchamiać w skryptach narzędzia awk. Jeśli Twoim celem jest po prostu użycie całego skryptu awk tylko i wyłącznie do symulowania pracy polecenia dirname, to możesz też skorzystać z nieco innej formy, w której używane są wygodne filtry wejścia i wyjścia.

Licencja

Copyright © 2008 by Paweł Wilk.

Powyższy program jest rozpowszechniany w nadziei, że będzie przydatny, ale bez żadnych gwarancji – wyrażonych wprost lub domyślnie – w tym bez gwarancji użyteczności lub przydatności do konkretnych celów. Używasz go na własne ryzyko i na własną odpowiedzialność.

Używając zamieszczonego powyżej programu, dystrybuując go, modyfikując lub zapisując go na nośniku służącym do przechowywania informacji, oświadczasz, że posługujesz się językiem angielskim i akceptujesz spisane w tym języku umowne regulacje określające warunki korzystania z programu zwane Licencją. Nazwa tej Licencji to GNU Lesser General Public License w wersji 3, a jej zasady zostały wyłożone w dokumencie dostępnym pod adresem http://www.fsf.org/licensing/licenses/lgpl-3.0.html. Nieoficjalne tłumaczenie Licencji możesz znaleźć na stronie Konrada Stobieckiego . Jeśli nie możesz połączyć się z witryną, na której przedstawiona jest treść Licencji, to aby ją uzyskać napisz pod adres:

Free Software Foundation
51 Franklin Street, Fifth Floor
Boston, MA 02110-1301
USA


This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see http://www.gnu.org/licenses/

Podziel się

Trackbacki

Użyj następującego trackbacka na swojej stronie:

http://randomseed.pl/trackbacks?article_id=awk-symulacja-polecenia-dirname&day=21&month=10&year=2008

Komentarze

(leave url/email »)

   Pomoc języka formatowania Obejrzyj komentarz