Я не могу понять, как перечислить различные пути в $PATHотдельности, чтобы они выглядели так:
/bin
/usr/bin
/usr/local/bin
и т.п.
Кто-нибудь знает правильную переменную для этого?
Я не могу понять, как перечислить различные пути в $PATHотдельности, чтобы они выглядели так:
/bin
/usr/bin
/usr/local/bin
и т.п.
Кто-нибудь знает правильную переменную для этого?
Ответы:
Попробуй sed:
$ sed 's/:/\n/g' <<< "$PATH"
Или tr:
$ tr ':' '\n' <<< "$PATH"
Или python:
$ python2 -c "import os; print os.environ['PATH'].replace(':', '\n')"
Здесь все вышеперечисленное заменит все вхождения :новыми строками \n.
python -c 'import sys;print sys.argv[1].replace(":","\n")' $PATH
python -c "print r'$PATH'.replace(':', '\n')"(с использованием необработанной строки в случае обратной косой черты)
trработал для меня (на Mac, кстати). Спасибо.
.bash_profile, добавьте это так:alias path='tr ":" "\n" <<< "$PATH"'
Используйте расширение параметров bash :
echo "${PATH//:/$'\n'}"
Это заменяет олл- :ин $PATHновой строкой ( \n) и печатает результат. Содержание $PATHостается без изменений.
Если вы хотите заменить только первое :, удалите вторую косую черту:echo -e "${PATH/:/\n}"
${parameter/pattern/string}
Используя IFS:
(set -f; IFS=:; printf "%s\n" $PATH)
IFSсодержит символы, по которым bash выполняет разбиение, поэтому команда IFSwith :делает bash-разбиение расширением $PATHon :. printfЗацикливает аргументы над строкой форматирования, пока аргументы не будут исчерпаны. Нам нужно отключить использование globbing (подстановочные символы), set -fчтобы подстановочные знаки в именах каталогов PATH не расширялись.
Использование xargs:
xargs -n1 -d: <<< $PATH
От man xargs
-n max-args
Use at most max-args arguments per command line.
-d delim
Input items are terminated by the specified character.
echo $PATH | xargs -n1 -d: echoизлишним или это не имеет значения?
echo $PATH | xargs -n1 -d: сделает то же самое для вас, но вы будете использовать еще одну оболочку. Первый из них оценит echo $PATHи перенаправит вывод в следующую оболочку, чтобы сделать все остальное.
Вот эквивалент в Go:
$ cat path.go
package main
import (
"fmt"
"os"
"strings"
)
func main() {
for _, p := range strings.Split(os.Getenv("PATH"), ":") {
fmt.Println(p)
}
}
$ go run path.go
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/home/nathan/.local/bin
/home/nathan/go/bin
Вот еще несколько подходов. Я использую PATHкаталоги, содержащие обратную косую черту, пробелы и даже новую строку, чтобы показать, что они должны работать с чем угодно (кроме той, cutкоторая не работает на новых строках ):
$ echo "$PATH"
/bin:usr/bin/:/usr/local/bin:/some\ horrible thing:/even
new lines
Некоторые способы Perl:
$ perl -pe 's/:/\n/g' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
В -pозначает «печать каждую строку ввода после применения сценария дается -e». Скрипт использует оператор подстановки ( s/oldnew/), чтобы заменить все :символами новой строки.
$ perl -lne 'print for split /:/' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
-lДобавляет символ новой строки к каждому printвызову. Здесь скрипт :разделяет свои входные данные, а затем перебирает каждый элемент split и печатает его.
$ perl -F: -ane '$"="\n";print "@F"' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
В -aмарке perlведет себя , как awk: он разделит каждый из входных линий на характере заданного -F(так :, здесь) и сохранить результат в массиве @F. Это $"специальная переменная Perl, «разделитель списка», значение которой печатается между каждым элементом печатного списка. Таким образом, установка новой строки приведет к print @listпечати каждого элемента, @listа затем новой строки. Здесь мы используем его для печати @F.
$ perl -F: -ane 'print join "\n", @F' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Та же идея, что и выше, только меньше в гольфе. Вместо того, чтобы использовать $", мы явно joinдобавляем массив с символами новой строки, а затем печатаем.
Просто grepс помощью PCRE magic:
$ grep -oP '(^|:)\K[^:]+' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
В -oмарки grepпечатать только совпадающую часть каждой строки, поэтому каждый матч печатается на отдельной строке. -PПозволяет Perl Compatible Regular Expressions (PCRE). Регулярное выражение ищет отрезки не :( [^:]+), которые следуют либо за началом строки ( ^), либо за :символом. Это \Kтрюк PCRE, который означает «отбросить все, что соответствует» до этой точки »и используется здесь, чтобы избежать печати :.
И cutрешение (это не работает на новых строках, но может иметь дело с обратными слешами и пробелами):
$ cut -d: -f 1- --output-delimiter=$'\n' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Используются следующие параметры, -d:которые устанавливают входной разделитель :, -f 1-что означает печать всех полей (от 1-го до конца), а также --output-delimiter=$'\n'устанавливают выходной разделитель. $'\n'Является ANSI C процитировать и способ напечатать символ новой строки в оболочке.
Во всех приведенных выше примерах я использую оператор bash (и некоторых других оболочек) здесь string ( <<<) для передачи строки в качестве входных данных для программы. Так command <<<"foo"эквивалентно echo -n "foo" | command. Обратите внимание, что я всегда цитирую "$PATH", без кавычек оболочка съела бы символ новой строки.
@ 7stud дал другой подход в комментариях, который слишком хорош, чтобы не включать:
$ perl -0x3a -l012 -pe '' <<<"$PATH"
Это то, что известно как гольф . -0Определяет входной разделитель записей в виде восьмеричного или шестнадцатеричного числа. Это то, что определяет «строку» и ее значение по умолчанию - \nсимвол перевода строки. Здесь мы устанавливаем его к :который x3aв шестнадцатеричном (TRY printf '\x3a\n'). Это -lделает три вещи. Во-первых, он удаляет разделитель входных записей ( $/) в конце каждой строки, эффективно удаляя :здесь, а во-вторых, он устанавливает разделитель выходных записей ( $\) на любое восьмеричное или шестнадцатеричное значение, которое ему дано ( 012есть \n). Если $\он определен, он добавляется в конец каждого printвызова, поэтому к каждому добавляется новая строка print.
-peБудет р Ринт каждый входной линии после применения сценария дается -e. Здесь нет сценария, потому что вся работа выполняется с помощью флагов, как описано выше!
perl -0x3a -l012 -pe '' <<<$PATH. Объяснение: -0устанавливает разделитель входной записи (указанный в шестнадцатеричной / восьмеричной нотации, x3A - двоеточие), -lделает две вещи: 1) разбивает разделитель входной записи, 2) устанавливает разделитель выходной записи, если он указан (в восьмеричной записи) 012 - новая строка). А -pцикл выводит значение $ _, которая будет каждая линии читать.
-Fинформацию. Я использую в -Fсочетании с -anгодами, я никогда не понимал, что одно подразумевает другие. Между прочим, я видел, как Серж упомянул Code Golf , но я думаю, что вам также понравятся Unix и Linux, если вы занимаетесь этим.
-lтакже добавляется разделитель выходных записей, который дается в конце каждого вызова печати. Фактически print всегда добавляет разделитель выходной записи $/к концу строки, если разделитель выходной записи определен. По умолчанию это undef. Так что -ljus устанавливает $/, и это заставляет print добавить символ новой строки в конец строки.
Вероятно, единственный способ, который не был упомянут, это то, как я использовал его годами:
echo $PATH | tr ":" "\n"
Итак, в ваш .profile или .bash_profile или что-то еще вы можете добавить:
alias path='echo $PATH | tr ":" "\n"'
Поскольку все языки сценариев уже заняты, я перейду к C. С помощью функции довольно легко получить переменные среды get_env()(см. Документацию библиотеки GNU C ). Остальное - просто манипуляция персонажем.
bash-4.3$ cat get_path.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *path = getenv("PATH");
int length = strlen(path) -1;
for(int i=0;i<=length;i++){
if (path[i] == ':')
path[i] = '\n';
printf("%c",path[i]);
}
printf("\n");
return 0;
}
bash-4.3$ gcc get_path.c
bash-4.3$ ./a.out
/home/xieerqi/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/opt/microchip/xc16/v1.25/bin
/opt/microchip/xc32/v1.40/bin
/opt/microchip/xc8/v1.35/bin
/home/xieerqi/bin
/home/xieerqi/bin/sh
Но также потому, что «почему бы и нет», вот альтернативная версия Python через аргументы командной строки sys.argv
python -c 'import sys; print "\n".join(sys.argv[1].split(":"))' "$PATH"
Ruby не поставляется с Ubuntu по умолчанию, в отличие от компилятора C и интерпретатора Python, но если вы когда-нибудь будете его использовать, решение в Ruby будет таким:
ruby -ne 'puts $_.split(":")' <<< "$PATH"
Как предлагает 7stud (спасибо большое!) В комментариях , это также можно сократить с помощью
ruby -F: -ane 'puts $F' <<<$PATH
и так
ruby -0072 -ne 'puts chomp' <<<$PATH
Мы можем использовать split()функцию, чтобы разбить строку, считанную в массив, и использовать for-eachцикл, чтобы распечатать каждый элемент на отдельной строке.
awk '{split($0,arr,":"); for(var in arr) print arr[var]}' <<< $PATH
putsавтоматически печатает элементы массива на отдельных строках! Вы также можете сделать так, чтобы переключатели делили: ruby -F: -ane 'puts $F' <<<$PATH Объяснение: -Fустанавливает $;указанный символ, который является разделителем по умолчанию, используемым String :: split ($; имеет значение по умолчанию nil, которое разделяется на пробел). -aвызывает $ _. split, где $ _ - строка, считываемая с использованием gets ()), и присваивает результирующий массив $F.
-Fфлаг - я только начинаю с Руби, поэтому делаю что-то немного грубым.
ruby -0072 -ne 'puts chomp' <<<$PATH. Объяснение: -0устанавливает разделитель входной записи (укажите символ в восьмеричном формате; 072 - двоеточие). Ruby использует $ _ аналогично Perl. Метод gets () (используемый в -nцикле) устанавливает $ _ для текущей строки, которая читается. И chomp()без аргумента chomps $ _. Мне все еще нравится твой лучше. :)
-Fфлагом, короче. Если вы это сделаете, echo "ruby -F: -ane 'puts $F' <<<$PATH" |wc -c это скажет мне, что это 271 байт, но тот, у которого восьмеричное число равно 276. Это для всей команды, конечно, если мы рассмотрим только код, puts $Fон явно короче. :) Кстати, вы знаете о Code Golf ? Это сайт для решения головоломок с минимальным количеством байтов. Есть вопрос, связанный с этим: codegolf.stackexchange.com/q/96334/55572
Нам нужно больше Java!
public class GetPathByLine {
public static void main(String[] args) {
for (String p : System.getenv("PATH").split(":")) {
System.out.println(p);
}
}
}
Сохраните это GetPathByLine.javaи скомпилируйте, используя:
javac GetPathByLine.java
Бежать с:
java GetPathByLine
┌─[17:06:55]─[kazwolfe@BlackHawk]
└──> ~ $ cat GetPathByLine.java
public class GetPathByLine {
public static void main(String[] args) {
for (String p : System.getenv("PATH").split(":")) {
System.out.println(p);
}
}
}
┌─[17:06:58]─[kazwolfe@BlackHawk]
└──> ~ $ javac GetPathByLine.java
┌─[17:07:02]─[kazwolfe@BlackHawk]
└──> ~ $ java GetPathByLine
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
python3 -c "import os; [print(p) for p in os.getenv('PATH').split(':')]"
Через awk.
echo $PATH | awk -F: '{for(i=1;i<=NF;i++)print $i}'
Через питона.
$ echo $PATH | python3 -c 'import fileinput
for line in fileinput.input():
for i in line.split(":"):
print(i)'
Обратите внимание, что отступы очень важны в Python.
echo $PATH | awk '{gsub(/\:/,"\n");print}'
fileinputкогда вы могли бы просто использовать input:python3 -c 'print(*input().split(":"), sep="\n")' <<< "$PATH"
Я использую «Функции пути Bash» Стивена Коллайера (см. Его статью в Linux Journal ). Это позволяет мне использовать «список через двоеточие» в качестве типа данных в программировании оболочки. Например, я могу создать список всех каталогов в текущем каталоге:
dirs="";for i in * ; do if [ -d $i ] ; then addpath -p dirs $i; fi; done
Затем listpath -p dirsвыдает список.
Объяснение для ответа @Cyrus
echo "${PATH//:/$'\n'}"
Заметки:
Цитирование ANSI-C - объясняет $ 'some \ ntext'
Расширение параметра оболочки - оно объясняет $ {параметр / шаблон / строку}. Если шаблон начинается с '/', все совпадения шаблона заменяются строкой.
Итак, мы имеем:
Другой способ AWK - рассматривать каждый каталог как отдельную запись , а не как отдельное поле .
awk 'BEGIN{RS=":"} {print $0}' <<<"$PATH"
Я нахожу этот синтаксис особенно интуитивным. Но, если хотите, вы можете сократить его, сделав print $0неявное (это действие по умолчанию, которое 1оценивается как true, вызывая его для каждой строки):
awk 'BEGIN{RS=":"} 1' <<<"$PATH"
По умолчанию в качестве разделителя входных и выходных записей AWK используется перевод строки. Устанавливая разделитель входной записи ( RS) :перед прочтением ввода, AWK автоматически анализирует разделенный двоеточиями $PATHв именах своих каталогов. AWK расширяется $0до каждой записи целиком, символ новой строки остается разделителем выходной записи, и зацикливание gsubне требуется.
ek@Io:~$ echo "$PATH"
/home/ek/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
ek@Io:~$ awk 'BEGIN{RS=":"} {print $0}' <<<"$PATH"
/home/ek/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
AWK часто используется для анализа записей в отдельных полях, но для этого не нужно просто составлять список имен каталогов.
Это работает даже для ввода, содержащего пробелы (пробелы и табуляции), даже несколько последовательных пробелов:
ek@Io:~$ awk 'BEGIN{RS=":"} {print $0}' <<<$'ab\t\t c:de fg:h'
ab c
de fg
h
То есть, если вы не заставите AWK перестроить запись (см. Ниже), нет проблем с наличием пробелов или табуляций (разделителей полей по умолчанию) на входе. Вы , PATHвероятно , не содержит пробелов на системе Ubuntu, но если это произойдет, это будет по- прежнему работать.
В качестве дополнительного примечания стоит упомянуть, что способность AWK интерпретировать запись как набор полей становится полезной для связанной проблемы построения таблицы компонентов каталога :
ek@Io:~$ awk -F/ 'BEGIN{RS=":"; OFS="\t"} {$1=$1; print $0}' <<<"$PATH"
home ek bin
usr local sbin
usr local bin
usr sbin
usr bin
sbin
bin
usr games
usr local games
snap bin
Любопытное $1=$1назначение служит для того, чтобы заставить AWK перестроить запись .
(Это, вероятно, более полезно для случаев, когда для компонентов требуется дополнительная обработка, чем для показанного точного примера простой печати таблицы.)
jq -Rr 'gsub(":";"\n")' <<<$PATH
Как отобразить пути в $ PATH отдельно
Это мои предпочтительные способы сделать это, основываясь на моих соответствующих сценариях использования и заботах о совместимости и использовании ресурсов.
trВо-первых, если вам нужно быстрое, легко запоминающееся и читаемое решение, просто введите эхо PATHи направьте его в translate ( tr), чтобы превратить двоеточия в новые строки:
echo $PATH | tr : "\n"
Недостатком является использование двух процессов из-за конвейера, но если мы просто взломали терминал, нас это действительно волнует?
Если вам нужно довольно постоянное решение .bashrcдля интерактивного использования, вы можете использовать псевдоним для следующей команды path, но читаемость этого решения сомнительна:
alias path="echo \"${PATH//:/$'\n'}\""
Если шаблон начинается с '/', все совпадения шаблона заменяются строкой. Обычно заменяется только первый матч.
Приведенная выше команда заменяет двоеточие символами новой строки, используя расширение параметров оболочки Bash :
${parameter/pattern/string}
Чтобы объяснить это:
# v--v---------delimiters, a'la sed
echo "${PATH//:/$'\n'}"
# ^^ ^^^^^----string, $ required to get newline character.
# \----------pattern, / required to substitute for *every* :.
Удачи, помня об этом, когда вы просто взламываете командную строку, если вы еще не добавили псевдоним.
В качестве альтернативы, достаточно кросс-совместимый, читаемый и понятный подход, который не зависит ни от чего, кроме оболочки, использует следующую функцию (я предлагаю в вашей .bashrc.)
Следующая функция временно делает Внутренний (или Входной) Разделитель Полей (IFS) двоеточием, и когда массив присваивается printf, он выполняется, пока массив не будет использован:
path () {
local IFS=:
printf "%s\n" ${PATH}
}
Этот метод создания функции , IFSи printfобеспечиваются за счет POSIX, поэтому он должен работать в большинстве Posix-подобных оболочек (особенно тире, который Ubuntu обычно псевдонимы sh).
Вы должны использовать Python для этого? Ты мог бы. Это самая короткая команда Python, о которой я могу подумать:
python -c "print('\n'.join('${PATH}'.split(':')))"
или только Python 3 (и, возможно, более читабельный?):
python3 -c "print(*'${PATH}'.split(':'), sep='\n')"
Они также должны работать в любой обычной оболочке, если у вас есть Python.
Это решение проще, чем Java , C , go и awk :
$ LPATH=$PATH wine cmd /c echo %LPATH::=$'\n'% 2> /dev/null
/usr/local/bin
/usr/local/sbin
/usr/bin
/usr/sbin
Вот еще одна отличная возможность:
$ jrunscript -classpath /usr/share/java/bsh.jar -e 'print(java.lang.System.getenv("PATH").replaceAll(":","\n"))'
/usr/local/bin
/usr/local/sbin
/usr/bin
/usr/sbin
Это потребует установки некоторых зависимостей:
sudo apt-get install openjdk-8-jdk-headless bsh