Я не можу зрозуміти, як перелічити різні шляхи $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, btw). Дякую.
.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 робить розбиття, тому a IFS
з :
робить bash split розширенням $PATH
на :
. printf
цикли аргументів за рядком формату, поки аргументи не будуть вичерпані. Нам потрібно вимкнути глобалізацію (розширення підстановки), використовуючи, set -f
щоб символи підстановки в іменах каталогу PATH не розширювалися.
Використання xargs
:
xargs -n1 -d: <<< $PATH
-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
виклику. Тут сценарій розділяє свій вклад на, :
а потім петлює над кожним розділеним елементом і друкує його.
$ 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 магія:
$ grep -oP '(^|:)\K[^:]+' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
У -o
марки grep
друкувати тільки збігається частина кожного рядка, тому кожен матч друкується на окремому рядку. -P
Дозволяє Perl Compatible Regular Expressions (PCRE). Режекс шукає відрізки non- :
( [^:]+
), які слідують або за початком рядка ( ^
), або за :
символом. Це \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
в шістнадцятковій спробі (спробуйте 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
також додається роздільник записів вихідних даних, що надається в кінці кожного друку. Фактично, друк завжди додає роздільник запису виводу $/
, в кінець рядка - якщо визначено роздільник записів на вихід. За замовчуванням це значення undef. Так -l
встановлюється jus $/
, і це призводить до того, що друк додає новий рядок до кінця рядка.
Оскільки всі мови сценаріїв уже взяті, я перейду з 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 ($; має значення за замовчуванням нуль, яке розбивається на пробіли). -a
викликає $ _. split, де $ _ - рядок, зчитувана з використанням get ()) і присвоює отриманий масив $F
.
-F
прапор - я тільки починаю з Рубі, тому роблю справи трохи грубо.
ruby -0072 -ne 'puts chomp' <<<$PATH
. Пояснення: -0
встановлює роздільник запису вхідних даних (вкажіть символ у восьмеричному форматі; 072 - двокрапка). Рубі використовує $ _ способами, схожими на Perl. Метод get () (використовується в -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
Напевно, єдиний спосіб, про який не згадували, - це те, як я його використовую роками:
echo $PATH | tr ":" "\n"
тож у свій .profile або .bash_profile чи будь-що інше ви можете додати:
alias path='echo $PATH | tr ":" "\n"'
Нам потрібно більше 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"
Я використовую "Баш-шлях шляху" Стівена Коллієра (див. Його статтю в 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
оцінюється як істинне, внаслідок чого це робиться для кожного рядка):
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
його та перекладіть,tr
щоб перекласти ( ), щоб перетворити колонки на нові рядки:
echo $PATH | tr : "\n"
Має недолік використання двох процесів через трубу, але якщо ми просто злому в терміналі, чи нас справді це хвилює?
Якщо ви хочете досить .bashrc
інтерактивне рішення у вашому інтерактивному використанні, ви можете вказати наступну команду path
, але читабельність цього рішення сумнівна:
alias path="echo \"${PATH//:/$'\n'}\""
Якщо шаблон починається з '/', всі збіги шаблону замінюються рядком. Зазвичай замінюється лише перший матч.
Вищевказана команда замінює двокрапки на нові рядки, використовуючи розширення параметру оболонки Баша :
${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 and 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