Albo bardziej ogólnie, jak usunąć element z listy rozdzielanej dwukropkami w zmiennej środowiskowej Bash?
Wydawało mi się, że lata temu widziałem prosty sposób, aby to zrobić, wykorzystując bardziej zaawansowane formy rozwijania zmiennych Bash, ale jeśli tak, to straciłem z oczu. Szybkie wyszukiwanie w Google przyniosło zaskakująco mało trafnych wyników i żadnego, który nazwałbym „prostym” lub „eleganckim”. Na przykład dwie metody używające odpowiednio sed i awk:
PATH=$(echo $PATH | sed -e 's;:\?/home/user/bin;;' -e 's;/home/user/bin:\?;;')
PATH=!(awk -F: '{for(i=1;i<=NF;i++){if(!($i in a)){a[$i];printf s$i;s=":"}}}'<<<$PATH)
Czy nie istnieje nic prostego? Czy jest coś podobnego do funkcji split () w Bash?
Aktualizacja:
Wygląda na to, że muszę przeprosić za moje celowo niejasne pytanie; Byłem mniej zainteresowany rozwiązaniem konkretnego przypadku użycia niż sprowokowaniem dobrej dyskusji. Na szczęście mam to!
Jest tu kilka bardzo sprytnych technik. W końcu dodałem do mojego zestawu narzędzi następujące trzy funkcje. Magia dzieje się w path_remove, która w dużej mierze opiera się na sprytnym wykorzystaniu awk
zmiennej RS przez Martina Yorka .
path_append () { path_remove $1; export PATH="$PATH:$1"; }
path_prepend () { path_remove $1; export PATH="$1:$PATH"; }
path_remove () { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '$0 != "'$1'"' | sed 's/:$//'`; }
Jedynym prawdziwym okrucieństwem jest użycie sed
do usunięcia końcowej okrężnicy. Biorąc jednak pod uwagę, jak prosta jest reszta rozwiązania Martina, jestem całkiem skłonny z tym żyć!
Powiązane pytanie: Jak manipulować elementami $ PATH w skryptach powłoki?
źródło
WORK=`echo -n ${1} | awk -v RS=: -v ORS=: '$0 != "'${3}'"' | sed 's/:$//'`; eval "export ${2}=${WORK}"
ale musisz ją nazwaćfunc $VAR VAR pattern
(na podstawie @ martin-york i @ andrew-aylett)Odpowiedzi:
Minuta z awk:
Edycja: odpowiedź na poniższe komentarze:
Edytuj w odpowiedzi na problem bezpieczeństwa: (nie dotyczy pytania)
Spowoduje to usunięcie wszelkich końcowych dwukropków pozostawionych przez usunięcie ostatnich wpisów, co skutecznie dodałoby
.
ścieżkę.źródło
PATH
zmiennej robi , jako przepis szczególny, oznaczają bieżący katalog wszystkich powłok uniksowych od przynajmniej V7 Unix 1979. To wciąż robi wbash
. Sprawdź instrukcję lub spróbuj sam.Mój brudny hack:
źródło
Ponieważ dużym problemem związanym z zastępowaniem są przypadki końcowe, co powiesz na to, aby przypadki końcowe nie różniły się od innych przypadków? Jeśli ścieżka miała już dwukropki na początku i na końcu, moglibyśmy po prostu wyszukać nasz żądany ciąg zawinięty w dwukropki. W tej chwili możemy łatwo dodać te dwukropki i później je usunąć.
Czysty bash :).
źródło
WORK
iPATH
ponieważ rozwijanie zmiennych następuje po przeanalizowaniu wiersza na sekcje w celu przypisania zmiennych i wykonania poleceń.REMOVE
może wymagać cudzysłowu lub możesz po prostu wstawić swój ciąg bezpośrednio do zamiany, jeśli jest to stała.Oto najprostsze rozwiązanie, jakie mogę wymyślić:
Powyższy przykład usunie każdy element w $ PATH, który zawiera „usr”. Możesz zamienić „* usr *” na „/ home / user / bin”, aby usunąć tylko ten element.
aktualizacja na sschuberth
Mimo że uważam, że przestrzenie w a
$PATH
to okropny pomysł, oto rozwiązanie, które sobie z tym radzi:lub
źródło
Oto jedna linijka, która pomimo aktualnie akceptowanych i najwyżej ocenianych odpowiedzi, nie dodaje niewidocznych znaków do PATH i radzi sobie ze ścieżkami zawierającymi spacje:
Osobiście uważam, że jest to łatwe do odczytania / zrozumienia i obejmuje tylko typowe polecenia zamiast używania awk.
źródło
export PATH=$(p=$(echo $PATH | tr ":" "\0" | grep -v -z "/cygwin/" | tr "\0" ":"); echo ${p%:})
(choć prawdopodobnie możesz zadać sobie pytanie, dlaczego tego potrzebujesz, jeśli tak :))grep -v "^/path/to/remove\$"
lubgrep -v -x "/path/to/remove"
tr
jest bardziej powszechne niżawk
? ;)tr
a nie z tłumaczemawk
.echo "..."
zeprintf "%s" "..."
go do pracy na drogach, jak-e
i podobnych. Zobacz stackoverflow.com/a/49418406/102441Oto rozwiązanie, które:
IFS
,usuwa wszystkie wystąpienia argumentu w
PATH
.źródło
Wykopałem to z mojego pliku .bashrc. Kiedy bawisz się z PATH i gubisz się, awk / sed / grep staje się niedostępny :-)
źródło
Najlepsza opcja czystego basha, jaką do tej pory znalazłem, to:
Jest to oparte na niezupełnie poprawnej odpowiedzi na Dodaj katalog do $ PATH, jeśli jeszcze go tam nie ma na Superuser.
źródło
removePath () { PATH=${PATH/":$1"/}; PATH=${PATH/"$1:"/}; }
$PATH
folder zawiera podfolder ścieżki docelowej (tj. Do usunięcia). Na przykład:a:abc/def/bin:b
->a/bin:b
, kiedyabc/def
ma zostać usunięty.Właśnie korzystałem z funkcji w dystrybucji bash, które były tam najwyraźniej od 1991 roku. Są one nadal w pakiecie bash-docs w Fedorze i były używane w
/etc/profile
, ale nie więcej ...źródło
Napisałem odpowiedź na to tutaj (używając również awk). Ale nie jestem pewien, czy tego szukasz? Przynajmniej wydaje mi się jasne, co robi, zamiast próbować dopasować się do jednej linii. Jednak w przypadku prostej wkładki, która usuwa tylko rzeczy, polecam
Wymiana jest
lub (krótszy, ale mniej czytelny)
W każdym razie, jeśli chodzi o to samo pytanie i wiele przydatnych odpowiedzi, zobacz tutaj .
źródło
awk '$0 !~ "/bin"'
. To znaczy zachowuj wiersze niezawierające „/ bin” z operatorem awk!~
.Cóż, w bashu, ponieważ obsługuje wyrażenia regularne, po prostu zrobiłbym:
źródło
Podoba mi się trzy funkcje przedstawione w aktualizacji @ BenBlank do jego pierwotnego pytania. Aby je uogólnić, używam 2-argumentowego formularza, który pozwala mi ustawić PATH lub dowolną inną zmienną środowiskową, którą chcę:
Przykłady użycia:
Zauważ, że dodałem również kilka cudzysłowów, aby umożliwić prawidłowe przetwarzanie ścieżek zawierających spacje.
źródło
Co jest bardziej eleganckie niż awk?
Pyton! Jest to bardziej czytelne i łatwiejsze w utrzymaniu rozwiązanie i łatwo jest sprawdzić, czy naprawdę robi to, czego chcesz.
Powiedz, że chcesz usunąć pierwszy element ścieżki?
(Zamiast potoku z
echo
,os.getenv['PATH']
byłby trochę krótszy i dałby taki sam wynik jak powyżej, ale martwię się, że Python może zrobić coś z tą zmienną środowiskową, więc prawdopodobnie najlepiej jest przesłać ją bezpośrednio ze środowiska, na którym Ci zależy .)Podobnie usunąć z końca:
Aby uczynić te funkcje powłoki wielokrotnego użytku, które możesz na przykład umieścić w swoim pliku .bashrc:
źródło
Tak, na przykład umieszczenie dwukropka na końcu ścieżki PATH sprawia, że usunięcie ścieżki jest nieco mniej niezgrabne i podatne na błędy.
źródło
Jeśli obawiasz się usuwania duplikatów w $ PATH, najbardziej eleganckim sposobem, IMHO, byłoby nie dodawanie ich w pierwszej kolejności. W 1 linii:
Folder $ można zastąpić czymkolwiek i może on zawierać spacje („/ home / user / moje dokumenty”)
źródło
Najbardziej eleganckie rozwiązanie bash, jakie do tej pory znalazłem:
źródło
Większość innych proponowanych rozwiązań polegać tylko na dopasowanie strun i nie biorą pod uwagę segmenty ścieżki zawierające specjalne nazwy podoba
.
,..
albo~
. Funkcja bash poniżej rozwiązuje łańcuchy katalogów w swoim argumencie oraz w segmentach ścieżki, aby znaleźć logiczne dopasowania katalogów, a także dopasowania łańcuchów.Test:
źródło
Linux from Scratch definiuje trzy funkcje Bash w
/etc/profile
:Ref: http://www.linuxfromscratch.org/blfs/view/svn/postlfs/profile.html
źródło
Wiem, że to pytanie dotyczy BASH, które każdy powinien preferować, ale ponieważ lubię symetrię i czasami muszę używać "csh", zbudowałem odpowiednik "path_prepend ()", "path_append ()" i "path_remove () "eleganckie rozwiązanie powyżej.
Istota jest taka, że "csh" nie ma funkcji, więc umieściłem małe skrypty powłoki w moim osobistym katalogu bin, które działają jak funkcje. Tworzę aliasy do SOURCE tych skryptów, aby wprowadzić zmiany w wyznaczonej zmiennej środowiskowej.
~ / bin / _path_remove.csh:
~ / bin / _path_append.csh:
~ / bin / _path_prepend.csh:
~ / bin / .cshrc:
Możesz ich używać w ten sposób ...
źródło
Ponieważ jest to dość problematyczne, ponieważ NIE MA eleganckiego sposobu, zalecam uniknięcie problemu poprzez zmianę rozwiązania: zbuduj swoją ŚCIEŻKĘ zamiast próbować ją zburzyć.
Mógłbym być bardziej szczegółowy, gdybym znał Twój prawdziwy kontekst problemu. W międzyczasie użyję kompilacji oprogramowania jako kontekstu.
Typowym problemem związanym z kompilacjami oprogramowania jest to, że na niektórych komputerach psuje się, ostatecznie z powodu tego, jak ktoś skonfigurował domyślną powłokę (PATH i inne zmienne środowiskowe). Eleganckim rozwiązaniem jest uodpornienie skryptów budowania poprzez pełne określenie środowiska powłoki. Zakoduj skrypty kompilacji, aby ustawić PATH i inne zmienne środowiskowe w oparciu o elementy składające, które kontrolujesz, takie jak lokalizacja kompilatora, biblioteki, narzędzia, komponenty itp. Uczyń każdy konfigurowalny element czymś, co możesz indywidualnie ustawić, zweryfikować i następnie użyj odpowiednio w swoim skrypcie.
Na przykład mam kompilację Java opartą na Maven i ukierunkowaną na WebLogic, którą odziedziczyłem po moim nowym pracodawcy. Skrypt kompilacji jest znany z tego, że jest kruchy, a inny nowy pracownik i ja spędziliśmy trzy tygodnie (nie w pełnym wymiarze godzin, tylko tu i tam, ale wciąż wiele godzin), aby pracować na naszych maszynach. Istotnym krokiem było przejęcie kontroli nad PATH, aby dokładnie wiedzieć, która Java, która Maven i która WebLogic jest wywoływana. Utworzyłem zmienne środowiskowe, aby wskazywały na każde z tych narzędzi, a następnie obliczyłem PATH na podstawie tych i kilku innych. Podobne techniki oswoiły inne konfigurowalne ustawienia, aż w końcu stworzyliśmy odtwarzalną kompilację.
Nawiasem mówiąc, nie używaj Mavena, Java jest w porządku i kupuj WebLogic tylko wtedy, gdy absolutnie potrzebujesz jego klastrowania (ale poza tym nie, a zwłaszcza nie są to zastrzeżone funkcje).
Wszystkiego najlepszego.
źródło
PATH
. Jasne, możesz zbudować własne, ale za każdym razem, gdy administrator coś przenosi, musisz dowiedzieć się, gdzie to umieścił. Takie podejście podważa cel posiadania administratora.Podobnie jak w przypadku @litb, napisałem odpowiedź na pytanie „ Jak manipulować elementami $ PATH w skryptach powłoki ”, więc moja główna odpowiedź jest tam.
Funkcjonalność „rozdzielenia” w
bash
i innych pochodnych powłoki Bourne'a jest najlepiej osiągnięta za$IFS
pomocą separatora międzypolowego. Na przykład, aby ustawić pozycyjnych argumentów ($1
,$2
...) do elementów ścieżki, użytkowania:Będzie działać poprawnie, o ile w zmiennej $ PATH nie ma spacji. Sprawienie, by działało z elementami ścieżki zawierającymi spacje, to nietrywialne ćwiczenie - pozostawione zainteresowanemu czytelnikowi. Prawdopodobnie łatwiej jest sobie z tym poradzić za pomocą języka skryptowego, takiego jak Perl.
Mam też skrypt,
clnpath
którego często używam do ustawiania mojej PATH. Udokumentowałem to w odpowiedzi na pytanie „ Jak uniknąć duplikowania zmiennej PATH w csh ”.źródło
Irytującym problemem są przypadki słupków ogrodzeniowych wśród pierwszego i ostatniego elementu. Problem można elegancko rozwiązać, zmieniając IFS i używając tablicy, ale nie wiem, jak ponownie wprowadzić dwukropek po przekonwertowaniu ścieżki na postać tablicową.
Oto nieco mniej elegancka wersja, która usuwa jeden katalog z
$PATH
używania tylko manipulacji na łańcuchach. Przetestowałem to.źródło
Oto jedna linijka Perla:
$a
Zmienna uzyskuje ścieżkę do usunięcia. Polecenias
(substytut) iprint
niejawnie operują na$_
zmiennej.źródło
Dobre rzeczy tutaj. Używam tego, aby przede wszystkim nie dodawać duplikatów.
źródło
case ":$PATH:" in (*:"$nodup":*) ;; (*) PATH="$PATH:$nodup" ;; esac
Po włączeniu rozszerzonego globowania można wykonać następujące czynności:
źródło
Rozszerzony globbing jednoliniowy (cóż, w pewnym sensie):
Wydaje się, że nie ma potrzeby ucieczki przed ukośnikami w 1 dolarach.
źródło
Dodając dwukropki do PATH, moglibyśmy również zrobić coś takiego:
źródło
W path_remove_all (przez proxxy):
źródło
Chociaż jest to bardzo stary wątek, pomyślałem, że to rozwiązanie może być interesujące:
znalazłem to w tym poście na blogu . Myślę, że ten mi się najbardziej podoba :)
źródło
Przyjąłem nieco inne podejście niż większość ludzi tutaj i skupiłem się konkretnie na manipulowaniu strunami, na przykład:
Powyższe jest uproszczonym przykładem końcowych funkcji, których używam. Stworzyłem również
path_add_before
ipath_add_after
umożliwiam wstawianie ścieżki przed / po określonej ścieżce już w PATH.Pełny zestaw funkcji jest dostępny w path_helpers.sh w moich plikach dot . W pełni obsługują usuwanie / dołączanie / poprzedzanie / wstawianie na początku / środku / końcu ciągu PATH.
źródło