Discussion:
Podmiana odwrotna zmiennych
(Wiadomość utworzona zbyt dawno temu. Odpowiedź niemożliwa.)
heby
2023-01-20 10:52:13 UTC
Permalink
Cześć.

Czy jest jakiś gotowiec, który pozwoli mi na taką sztuczkę:

1) dostanie plik tekstowy na stdin
2) każdy ciąg znaków w tym pliku, pasujący do wartości dowolnej zmiennej
env, zostanie zastapiony tą zmienną env
3) wypluje output na stdout

Czyli chodzi i operację odwrotną, do podstawiania wartości zmiennych. Ja
chcę dostać zmienne, zamiast wartości.

Po co?

Mam loga z kompilacji, mniej więcej takiego:

/home/foo/bar/spam/src/go.txt
/home/foo/bar/spam/src/buzz/main.c

A chcę dostac, w obecności zmiennej środowiskowej
SRC=/home/foo/bar/spam/src

... nastepujący output:

$SRC/go.txt
$SRC/buzz/main.c

Lub podobny, zamieniający wartosci na zmienne symboliczne.

Mogę go napisac, ale to nie jest wbrew pozorom łatwe (tzn aby zrobić to
wydajnie, bo grepami można łatwo i powoli ;). Ktoś coś widział w ten deseń?
heby
2023-01-20 11:05:53 UTC
Permalink
Post by heby
bo grepami można łatwo i powoli
Tfu, sedami ;)
marrgol
2023-01-21 23:10:27 UTC
Permalink
Post by heby
1) dostanie plik tekstowy na stdin
2) każdy ciąg znaków w tym pliku, pasujący do wartości dowolnej zmiennej
env, zostanie zastapiony tą zmienną env
Tak ogólnie postawionego zadania, bez dodatkowych warunków, raczej nie
da się dobrze wykonać -- trzeba dokładnie ustalić, co chce się uzyskać
z czego, to i napisanie skryptu/programu pewnie okaże się prostsze
(KISS, YAGNI).
Np. czy 'env' to na pewno musi być całe środowisko, w którym uruchomimy
skrypt, czy może wystarczyłby określony zbiór zmiennych potrzebnych
do uzyskania zamierzonego rezultatu?
Czy w obecności zmiennej 'AUDIO=pa' na pewno chcemy ze 'spam' uzyskać
's$AUDIOm' (albo raczej s${AUDIO}m, żeby to w ogóle miało sens)?
Czy przy zmiennych A=/home/foo i B=/foo/bar z '/home/foo/bar/go.txt'
chcemy otrzymać '$A/bar/go.txt' czy może '/home$B/go.txt'?
Czy przy A=/home/foo i B=/home/foo/bar z '/home/foo/bar/go.txt'
chcemy otrzymać '$A/bar/go.txt' czy może '$B/go.txt'?
Itd, itp…
Post by heby
3) wypluje output na stdout
Czyli chodzi i operację odwrotną, do podstawiania wartości zmiennych. Ja
chcę dostać zmienne, zamiast wartości.
Po co?
/home/foo/bar/spam/src/go.txt
/home/foo/bar/spam/src/buzz/main.c
A chcę dostac, w obecności zmiennej środowiskowej
SRC=/home/foo/bar/spam/src
$SRC/go.txt
$SRC/buzz/main.c
Lub podobny, zamieniający wartosci na zmienne symboliczne.
Mogę go napisac, ale to nie jest wbrew pozorom łatwe (tzn aby zrobić
to wydajnie, bo grepami można łatwo i powoli.
Łatwe czy nie, to pojęcie raczej względne… :-) Np. zakładając,
że sprawdzamy całe środowisko, ale pomijamy definicje funkcji
i puste zmienne, i podstawiamy nazwę pierwszej napotkanej
pasującej zmiennej tylko na początku linii z logu, rezultat
taki jak w powyższym przykładzie można uzyskać takim krótkim
(czytaj: łatwym i wydajnym ;-)) skryptem w perlu:

while(<>) {
foreach $K (keys %ENV) {
unless ($ENV{$K} =~ "{" or $ENV{$K} eq "") {
s/$ENV{$K}/\${$K}/, last if (/^$ENV{$K}/);
}
}
print;
}

No ale bez znajomości wszystkich „a co w przypadku, gdy” to tylko
taka luźna, uproszczona propozycja -- może wystarczy, a może nie.
Post by heby
Ktoś coś widział w ten deseń?
Znalezienie gotowca jest MZ mało prawdopodobne.
--
mrg
heby
2023-01-25 08:37:00 UTC
Permalink
Post by marrgol
Czy w obecności zmiennej 'AUDIO=pa' na pewno chcemy ze 'spam' uzyskać
's$AUDIOm' (albo raczej s${AUDIO}m, żeby to w ogóle miało sens)?
Nie ma. Dlatego na razie nie ograniczam koncepcji narzędzia. Szukam
czegoś, co łyknie 100MB takiego pliku i zrobi to kilkadziesiąt razy
dziennie, na kilkunastu zmiennych do podmiany. sedy się nie nadają z
uwagi na wydajność. A jak coś się znajdzie, to się zobaczy, czy użyteczne.
Post by marrgol
Post by heby
Mogę go napisac, ale to nie jest wbrew pozorom łatwe (tzn aby zrobić
to wydajnie, bo grepami można łatwo i powoli.
Łatwe czy nie, to pojęcie raczej względne… :-)  Np. zakładając,
że sprawdzamy całe środowisko, ale pomijamy definicje funkcji
i puste zmienne, i podstawiamy nazwę pierwszej napotkanej
pasującej zmiennej tylko na początku linii z logu, rezultat
taki jak w  powyższym przykładzie można uzyskać takim krótkim
while(<>) {
  foreach $K (keys %ENV) {
    unless ($ENV{$K} =~ "{" or $ENV{$K} eq "") {
      s/$ENV{$K}/\${$K}/, last if (/^$ENV{$K}/);
    }
  }
  print;
}
Tak, mam coś takiego, tylko raczej sed | sed |sed aby wykorzystać
współbieżność.
Jacek Marcin Jaworski
2023-01-23 17:08:36 UTC
Permalink
Napisz ile jest to stówek ten gotowiec i będzie.
heby
2023-01-25 08:38:50 UTC
Permalink
Post by Jacek Marcin Jaworski
Napisz ile jest to stówek ten gotowiec i będzie.
Przebijam: napiszę taniej, bo w ramach projektu. Ale zanim napiszę, to
szukam gotowego rozwiązania, bo kwadratowe koła, ale własne,
niekoniecznie są najlepszą opcją.

Loading...