Użyj sed zamiast zmiennej pliku zamiast pliku

30

Powiedziano mi, że było to możliwe, ale bez jednego działającego przykładu, który sedmoże odczytać zmienną łańcuchową bez potrzeby pliku wejściowego. Muszę go jeszcze uruchomić. Dla ogólnego bezpieczeństwa piszę $PATHzmienną do innej zmiennej, ponieważ mam z tym problem, ponieważ nie potrzebuję innych problemów, dopóki nie będę wiedział, jak to zrobić.

Rozważ następujące:

~$x=$PATH
~$sed -i 's/:/ /g' $x

to się nie powiedzie z: Brak takiego pliku lub katalogu.

Oto kilka innych, które próbowałem:

~$ sed -i 's/:/ /g' | (read x) 
sed: no input files
~$ sed -i 's/:/ /g' | (read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
sed: no input files
~$ sed -i 's/:/ /g' | $(read x) 
sed: no input files
~$ sed -i 's/:/ /g' | $(read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
sed: no input files
~$ sed -i 's/:/ /g' < $(read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
bash: $(read $x): ambiguous redirect
~$ sed -i 's/:/ /g' < read $x 
bash: read: No such file or directory
~$ sed -i 's/:/ /g' < (read x) 
bash: syntax error near unexpected token `('
~$ sed -i 's/:/ /g' < $((read x)) 
bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: syntax error: operand expected (error token is "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games")
~$ sed -i 's/:/ /g' < $((read $x)) 
bash: read /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: division by 0 (error token is "usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games")
~$ sed -i 's/:/ /g' << $((read $x)) 
> ;^C
~$ sed -i 's/:/ /g' << $(read $x)
> ;^C
~$ sed -i 's/:/ /g' $x
sed: can't read /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: No such file or directory
~$ sed -i 's/:/ /g' < $x
bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: No such file or directory
~$ sed -i 's/:/ /g' < echo $x
bash: echo: No such file or directory
~$ sed -i 's/:/ /g' |  echo $x
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
sed: no input files

Czy to w ogóle może działać? Wolałbym nie pisać niepotrzebnych plików, aby móc korzystać z sed. W tym konkretnym przykładzie, gdyby ~$x=$PATH ~$sed -i 's/:/ /g' $xrzeczywiście działał tak, jak chciałbym, uzyskałbym:

/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /usr/games /usr/local/games

który mógłbym następnie przypisać do zmiennej i użyć w przyszłych poleceniach, takich jak ls $x

j0h
źródło
1
x=$(echo "$x" | sed 's/:/ /g')?
heemayl

Odpowiedzi:

16

Może:

~$ x="$PATH"
~$ x="$(echo $x | sed 's/:/ /g')"
~$ echo "$x"
/usr/local/bin /usr/bin /bin /usr/local/games /usr/games
bolichep
źródło
@ jOh --- zauważ, że sedtutaj nie działa „zmienna łańcuchowa” (?), ale standardowe wejście --- tak właśnie powinno być.
Rmano,
myślę, że źle
zwrócę się
4
@ j0h to nie ma nic wspólnego sed, jest to pytanie, w jaki sposób powłoka przekierowuje dane wejściowe. sedzajmuje się strumieniami wejściowymi i odczytuje je przez standardowe wejście. Nie ma znaczenia, czy będą to pliki, czy nie. Potrafi zaakceptować wszystko, o ile przechodzi przez standardowe wejście.
terdon
38

Nie ma to nic wspólnego z sedtym, dotyczy każdego programu, który odczytuje standardowe dane wejściowe. W każdym razie to, czego szukałeś, to

sed 's/:/ /g' <<<"$PATH"

Nie ma powodu, aby zapisywać w innej zmiennej, nic, co zrobisz w ten sposób, nie wpłynie na wartość przechowywaną w zmiennej. Potrzebujesz do tego operatora przypisania ( =). Użyta powyżej składnia nazywa się „ciągiem tutaj” i jest specyficzna dla bash, ksh i zsh. Służy do przekazywania wartości zmiennej jako danych wejściowych do programu, który odczytuje ze standardowego wejścia.

Napisałem odpowiedź na temat U&L, która zawiera listę wszystkich różnych operatorów powłok, takich jak ten. Możesz rzucić okiem.

Pamiętaj, że mógłbyś to zrobić

echo "$PATH" | sed 's/:/ /g' 

Wreszcie, naprawdę nie potrzebujesz seddo tego wcale. Możesz zrobić wszystko bezpośrednio w bash:

echo "${PATH//:/ }"

Powyżej jest konstrukcją zastępczą bash. Biorąc pod uwagę zmienną $var, wzór pati zastępstwo ( rep), aby zastąpić wszystkie wystąpienia patz rep, zrobiłbyś

echo "${var//pat/rep}"

To samo z jednym ukośnikiem zastępuje tylko pierwsze wystąpienie:

echo "${var/pat/rep}"
terdon
źródło
2
Dzięki za „konstrukcję zastępującą bash”. Byłem w stanie użyć: „$ {1 / from / to}” w funkcji Bash, aby zmienić pierwszy argument na kolejne parametry.
AAAfarmclub