Mam plik tekstowy w następującym formacie:
keyword value
keyword value
...
Gdzie słowo kluczowe jest pojedynczym słowem, a wartość to wszystko inne do końca wiersza. Chcę odczytać plik ze skryptu powłoki, w taki sposób, aby wartości (ale nie słowa kluczowe) podlegały rozszerzaniu powłoki.
Z sed łatwo dopasować słowa kluczowe i wartościować części
input='
keyword value value
keyword "value value"
keyword `uname`
'
echo "$input"|sed -e 's/^\([^[:space:]]*\)[[:space:]]\(.*\)$/k=<\1> v=<\2>/'
który produkuje
k=<keyword> v=<value value>
k=<keyword> v=<"value value">
k=<keyword> v=<`uname`>
ale pytanie brzmi: w jaki sposób mogę osadzić polecenie powłoki w zastępczej części wyrażenia sed. W tym przypadku chciałbym, aby zastąpienie było \1 `echo \2`
.
Odpowiedzi:
Standardowy sed nie może wywoływać powłoki ( GNU sed ma do tego rozszerzenie , jeśli zależy ci tylko na niewbudowanym Linuksie), więc będziesz musiał wykonać część przetwarzania poza sed. Istnieje kilka rozwiązań; wszystkie wymagają starannego cytowania.
Nie jest jasne, w jaki sposób chcesz rozszerzyć wartości. Na przykład, jeśli linia to
który z poniższych wyników powinien być?
Omówię kilka możliwości poniżej.
czysta skorupa
Możesz uzyskać powłokę do odczytu linii wejściowej po linii i przetworzenia jej. Jest to najprostsze rozwiązanie, a także najszybsze w przypadku krótkich plików. To jest najbliższe wymaganiu „
echo \2
”:read -r keyword value
ustawia$keyword
na pierwsze słowo linii rozdzielane spacjami, a$value
na resztę linii minus końcowe spacje.Jeśli chcesz rozwinąć odwołania do zmiennych, ale nie wykonujesz poleceń poza podstawieniami poleceń, umieść
$value
w tym dokumencie dokument . Podejrzewam, że tego właśnie tak naprawdę szukałeś.sed wpięty do muszli
Możesz przekształcić dane wejściowe w skrypt powłoki i to ocenić. Sed spełnia swoje zadanie, choć nie jest to takie proste. Zgodnie z wymaganiem „
echo \2
” (pamiętaj, że musimy unikać pojedynczych cudzysłowów w słowie kluczowym):Przechodząc do dokumentu tutaj, nadal musimy uciec od słowa kluczowego (ale inaczej).
Jest to najszybsza metoda, jeśli masz dużo danych: nie rozpoczyna osobnego procesu dla każdej linii.
awk
Te same techniki, których używaliśmy przy sed, działają z awk. Powstały program jest znacznie bardziej czytelny. Idąc z „
echo \2
”:Korzystanie z dokumentu tutaj:
źródło
Mając GNU
sed
możesz użyć następującego polecenia:Które wyjścia:
z danymi wejściowymi.
Wyjaśnienie:
Polecenie sed pomija regularne wyjście za pomocą
-n
opcji.-r
jest przekazywany w celu użycia rozszerzonych wyrażeń regularnych, co oszczędza nam ucieczki od specjalnych znaków w szyku, ale nie jest to wymagane.s
Polecenie jest wykorzystywany do przesyłania linii wejściowej do polecenia:Słowo kluczowe get podało wartość not. Podaję opcję
e
- która jest specyficzna dla GNU -s
komendzie, która każe sedowi wykonać wynik podstawienia jako komendę powłoki i czytam jego wyniki w buforze wzorców (nawet wiele linii). Użycie opcjip
po (!)e
Powodujesed
wydrukowanie bufora wzorów po wykonaniu polecenia.źródło
-n
i,p
tjsed -r 's/([^ ]+) (.*)/echo "\1" \2\n/e' input
. Ale dzięki za to! Nie wiedziałem o teje
opcji.e
opcję (wprowadzoną przez GNU). Czy to nadalsed
? :)Możesz spróbować tego podejścia:
(jeśli dobrze zrozumiem twoją intencję). To znaczy wstaw „proces” na początku każdego niepustego wiersza, aby uczynić go skryptem:
do oceny (
eval
), gdzie proces jest funkcją, która drukuje oczekiwany komunikat.źródło
Jeśli akceptowalne jest rozwiązanie inne niż sed, ten fragment PERL wykona zadanie:
źródło
TYLKO KISS KRÓTKI CZYSTY SED
zrobię to
i działa.
źródło