Jak mogę usunąć cały tekst po znaku w bash?


147

Jak usunąć cały tekst po znaku, w tym przypadku dwukropkiem („:”), w bash? Czy mogę też usunąć okrężnicę? Nie mam pojęcia, jak to zrobić.

Odpowiedzi:


134

Przykład mógłby być przydatny, ale jeśli dobrze cię zrozumiałem, zadziałałoby:

echo "Hello: world" | cut -f1 -d":"

Spowoduje to konwersję „hello: world” na „hello”.


5
cutdziała, ale odpowiedź I Dennisa jest lepsza i bardziej elastyczna. Czy ktoś wie, czy wywołuje nowy proces, taki jak cut?
JoBu1324,

3
Lepiej jest korzystać z wbudowanych funkcji rozszerzania parametrów Basha niż generować podpowłoki uruchamiające narzędzia, takie jak basenamei cut, zobacz odpowiedź Dennisa poniżej
Louis Maddox,

1
cutmoże czytać ze standardowego wejścia, więc jest to lepsze, zwłaszcza gdy masz bardzo długi ciąg znaków, który musisz przetworzyć, np. zawartość pliku.
Sahas

1
I jak by to zastosować hello: world. To połowa odpowiedzi.
K - Toksyczność SO rośnie.

Można to zrobić przy użyciu składni zastępowania, takiej jak {var /: / ''}, ale działa tylko w bash ..
Mahesh

264

W Bash (i ksh, zsh, myślnik itp.) Możesz użyć interpretacji parametrów, %która usunie znaki z końca łańcucha lub #usunie znaki z początku łańcucha. Jeśli użyjesz jednego z tych znaków, najmniejszy pasujący ciąg zostanie usunięty. Jeśli podwoisz znak, najdłuższy zostanie usunięty.

$ a='hello:world'
$ b=${a%:*}
$ echo "$b"
hello
$ a='hello:world:of:tomorrow'
$ echo "${a%:*}"
hello:world:of
$ echo "${a%%:*}"
hello
$ echo "${a#*:}"
world:of:tomorrow
$ echo "${a##*:}"
tomorrow

6
Jest to natywna manipulacja ciągami powłoki, więc żadne dodatkowe procesy nie zostaną uruchomione. Odniesienie Bash Parametr Zmiana , Manipulacja Bash String i Better Bash skryptów
Dodzi Dzakuma

@denniswilliamson Jak mogłem usunąć 2 znaki po określonym ciągu, takim jak hello:worldbędzie hello:wo, używając ${a%:*}?
3kstc

Świetna odpowiedź, wielkie dzięki, ale miło będzie również dodać "${a##*:}"za zdobycie tylko tomorrow=)
avtomaton

1
@openCivilisation: Pewnie trzeba użyć dopasowywania wyrażeń regularnych następnie: a='hello:world:of:tomorrow'; pattern=''^([^:]*:).*$'; [[$ a = ~ $ wzór]]; echo "$ {BASH_REMATCH [1]}" ". To pasuje tylko do dwukropka. Jeśli chcesz, aby było to opcjonalne, musisz użyć innego wzorca. Wyjaśnienie wyrażeń regularnych Bash (i ogólnie wyrażeń regularnych) wykracza poza zakres tych komentarzy. Możesz znaleźć inne pytania, które omawiają ten problem lub opublikować własne.
Wstrzymano do odwołania.

1
@ kp123: To pierwszy przykład w mojej odpowiedzi. Za drugim razem, gdy to pokażę (gdzie usunięto słowo „jutro”), jest to prawie dokładnie sytuacja, o którą pytasz.
Wstrzymano do odwołania.


4
egrep -o '^[^:]*:'

czy możesz wyjaśnić, jak to zinterpretować, dziękuję.
rɑːdʒɑ

1
egrepjest grep with -E. Tutaj nie ma różnicy od zwykłego grep. -onakazuje grep wydrukować tylko część wiersza, która pasuje do wyrażenia. ^zakotwicza dopasowanie na początku wiersza. [^:]*dopasowuje zero lub więcej znaków, które nie są tym :znakiem. :pasuje do znaku :.
cdhowie,


3

Załóżmy, że masz ścieżkę z plikiem w tym formacie:

/dirA/dirB/dirC/filename.file

Teraz potrzebujesz tylko ścieżki, która zawiera cztery „/”. Rodzaj

$ echo "/dirA/dirB/dirC/filename.file" | cut -f1-4 -d"/"

a twoje wyjście będzie

/dirA/dirB/dirC

Zaletą używania cut jest to, że możesz również wyciąć katalog uppest, a także plik (w tym przykładzie), więc jeśli wpiszesz

$ echo "/dirA/dirB/dirC/filename.file" | cut -f1-3 -d"/"

Twój wynik byłby

/dirA/dirB

Chociaż możesz zrobić to samo z drugiej strony ciągu, nie miałoby to większego sensu w tym przypadku, jak pisanie

$ echo "/dirA/dirB/dirC/filename.file" | cut -f2-4 -d"/"

prowadzi do

dirA/dirB/dirC

W innych przypadkach ostatni przypadek może być również pomocny. Pamiętaj, że na początku ostatniego wyjścia nie ma znaku „/”.


2
Co zrobić, jeśli masz katalog „/resources/views/admin/users/relationships/posts.blade.php” i chcesz skrócić wszystko po OSTATNIM wystąpieniu „/”, biorąc pod uwagę, że NIE wiesz ile „/ „znaki są w ciągu. Dlatego chciałbym, aby wynik wyglądał następująco: „/ zasoby / widoki / admin / użytkownicy / relacje /” (lub nawet / zasoby / widoki / admin / użytkownicy / relacje bez końcowego ukośnika). Jak byś to zrobił?
kp123

-1

odetnij wszystko po ostatnim wystąpieniu „:”

cat fileListingPathsAndFiles.txt | grep -o '^.*:'

i jeśli chcesz porzucić to ostatnie „:”

cat file.txt | grep -o '^.*:' | sed 's/:$//'

@ kp123: którą chcesz zamienić :z /(gdzie sed jelita grubego powinny być \/)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.