Bash: Ucieczka z listy plików

-1

Czy można to zrobić ładniej (powtórz symbol zastępczy dla innego polecenia)

echo $(for x in *;do echo $x|sed 's/\([ \t\n\r\v\f\;#]\)/\^\1/g'|sed 's/$/\;/g';done)

Ponadto nie powinno być; po ostatniej nazwie pliku.

przykładowe użycie polecenia „doit” to

doit files[ list-of-files ] 'flags[foo;bar;other^ flag]options[value^ 1[1]value^ array[1;2;3]]'

itp.

Możliwe jest wewnętrzne opuszczanie białych znaków (w doit), ponieważ nie wpływa to na tokenizer doits (po prostu zjada każdą białą spację, która nie następuje ^). Oprócz dobrej rozszerzalności składni kod do odczytu plików konfiguracyjnych i wiersz poleceń są takie same.

Sed działa, oczekując, że doda; za dużo na końcu. Jednak logika dodawania; wewnątrz doit nie jest trudne do wdrożenia, więc ten ostatni krok nie jest konieczny. Nie podoba mi się to, że potrzebuję pętli, aby uciec przed każdym argumentem osobno. Po prostu echo * | sed ... nie zrobiłby tego, ponieważ echo niszczy informacje (wypisuje wszystko ograniczone przez białe znaki).

Podobny problem: chcę dodać echo ~ / my_progs / * dwukropek oddzielony do zmiennej ścieżki.

użytkownik877329
źródło
1
Dlaczego po prostu nie naprawić polecenia, aby właściwie obsługiwać argumenty?
Ignacio Vazquez-Abrams
1
Czy możesz nam powiedzieć, co naprawdę musisz zrobić lub dlaczego? Jak powiedział Ignacio, jest to prawdopodobnie kwestia prawidłowej interpretacji argumentów, a nie zmuszania ich do jakiegoś formatu. Zobacz także: mywiki.wooledge.org/XyProblem
slhck
1
Hm Prawdopodobnie byłoby łatwiej, gdybyś mógł pokazać nam przykładową listę plików i dokładny format doitwymagany przez tę magię . A może twoje polecenie działa już idealnie i szukasz czegoś „ładniejszego”, ponieważ…?
slhck
1
Jak powiedział @slhck, potrzebujemy przykładu danych wejściowych i oczekiwanych wyników, a najlepiej nieuchwytnych, doitaby odpowiedzieć.
terdon
1
Jeśli jej dodając dodatkowy ;prostu usunąć ostatnią sedkomendę: sed 's/$/\;/g'. Wyraźnie mówisz, aby dodać ;na końcu. Prawdopodobnie istnieje na to lepszy sposób, ale nie możemy go znaleźć, chyba że podasz nam konkretne przykłady. Zależy od Ciebie.
terdon

Odpowiedzi:

1

Nie jest jasne, co próbujesz zrobić, ale na podstawie „listy zmian plików”. Myślę, że to jest rozwiązanie:

IFS=$(echo -en "\n\b");
for file in $list; do
  sed -i 's/before/after/g' "$file";
done;

Ustawienie zmiennej środowiskowej IFS (Internal File Separator) na to spowoduje prawidłowe rozdzielenie plików na podstawie podziałów linii.


Lub ewentualnie użyj, findjeśli nie chcesz używać pętli.

doit() { find -name "$@" -exec sed -i 's/before/after/g' {} \; }
doit myfiles*txt
tylko przeglądam
źródło
0

Chciałem to zrobić bezpośrednio w powłoce, ale kompilacja programu w C działa lepiej. Z perspektywy powłoki jest to „komputer kwantowy”: jeden op, który działa znacznie szybciej niż powyższy skrypt powłoki. Wydaje mi się, że potrzeba więcej czasu, aby spawn sed dla każdego pliku.

#include <cstdio>

int main(int argc, char* argv[])
    {
    if(argc==0)
        {return -1;}
    --argc;
    ++argv;
    while(argc)
        {
        const char* arg=*argv;
        while(*arg)
             {
             if(*arg>='\0' && *arg<=' ')
                 {putchar('^');}
             switch(*arg)
                 {
                 case '[':
                 case ']':
                 case ';':
                 case '^':
                 case '#':
                     putchar('^');
                 }
             putchar(*arg);
             ++arg;
             }
         --argc;
         if(argc)
             {putchar(';');}
         ++argv;
         }
    return 0;
    }
użytkownik877329
źródło