Jak uciec ze znaków specjalnych w ciągu?

Zakładając, że $file trzyma wartość nazwy pliku, powiedz Dr" A.tif. Jak w programowaniu bash mógłbym pominąć pojedynczy cudzysłów i każdy inny znak specjalny $file bez usuwania znaku specjalnego?

Aktualizacja z 9 lipca 2014 r.

Jako żądanie od @Gilles , następujący fragment kodu, który „nie jest w stanie obsłużyć Dr" A.tif:

files=$(find /path/ -maxdepth 1 -name "*.[Pp][Dd][Ff]" -o -name "*.[Tt][Ii][Ff]") echo "${files}" > ${TEMP_FILE} while read file do newfile=$(echo "${file}" | sed "s, ,\\ ,g") ## line 1 done < ${TEMP_FILE} 

Po wypróbowaniu odpowiedź od @Patrick w line 1, wydaje mi się, że działa. Ale jeśli mam plik taki jak Dr\^s A.tif, printf nie wydaje się pomocne, pokazuje mi Dr\^s\ A.tif. Jeśli spróbuję ręcznie na konsoli w ten sposób:

printf "%q" "Dr\^s A.tif"

Otrzymam takie dane wyjściowe:

Dr\\\^s\ A.tif

Masz pomysł, jak sobie z tym poradzić?

Komentarze

  • w czym kontekst czy spodziewasz się użyć $ file? czy też jest to problem z przypisaniem ciągu znaków ze znakiem specjalnym do $ file?
  • Właściwie polecenie find zwraca mi tablicę z listą plików. Następnie przechodzę przez tę listę plików do zmiennej $ file.
  • Tobie ' podano tutaj kilka poprawnych odpowiedzi, ale prawdopodobnie nie są to odpowiedzi na pytanie, które naprawdę ' zadajesz. Na podstawie twojego komentarza mocno podejrzewam, że ' jesteś na złej drodze. Nie możemy Ci pomóc ', ponieważ wciąż nie wyświetlasz swojego kodu. Zalecam jednak przeczytanie Dlaczego mój skrypt powłoki dławi się spacjami lub innymi znakami specjalnymi? jako tło. Pokaż swój skrypt i wyjaśnij, co chcesz zrobić.

Odpowiedz

Ty może w tym celu użyć wbudowanego printf z %q. Na przykład:

$ file="Dr" A.tif" $ printf "%q\n" "$file" Dr\"\ A.tif $ file=" foo$bar\baz`" $ printf "%q\n" "$file" \ foo\$bar\\baz\` 

Z dokumentacji basha na printf:

In addition to the standard format specifications described in printf(1) and printf(3), printf interprets: %b expand backslash escape sequences in the corresponding argument %q quote the argument in a way that can be reused as shell input %(fmt)T output the date-time string resulting from using FMT as a format string for strftime(3) 

Komentarze

  • To nie ' nie działa w niektórych przypadkach .eg kiedy musisz zachować cudzysłowy.
  • @ user3467349 działa dobrze z cudzysłowami. ' Obstawiam, że ' próbuję czegoś takiego jak printf '%s' "foo". Najpierw musisz zrozumieć, jak działa parsowanie argumentów w powłoce. Zobacz gnu.org/software/bash/manual/bash.html#Shell-Operation . # 2 dzieje się przed # 6.
  • Czy możesz podaj przykład tego ciągu wydrukowanego za pomocą printf i żadnych innych manipulacji It doesn't have a: ""
  • Twój problem nie ma nic wspólnego z printf. Twoim problemem jest to, że nie ' nie chcesz, aby powłoka analizowała twój ciąg. Aby to zrobić, musisz przekazać swoje dane wejściowe do powłoki w taki sposób, aby nie ' nawet próbowały je przeanalizować. Jednym ze sposobów byłoby read -r -p 'input: ' && printf '%q\n' "$REPLY" i podanie danych wejściowych po wyświetleniu monitu.
  • Jak powiedziałem ' kilka razy. Brak wiedzy, jak przekazać surowe dane do powłoki, nie jest ' t problemem z printf. Być może powinieneś raczej zadać pytanie niż krytykować rozwiązanie, które nie ma nic wspólnego z twoim problemem.

Odpowiedź

Spróbuj: –

file=Dr\"\ A.tif echo $file Dr" A.tif 

lub

file="Dr" A.tif" echo $file Dr" A.tif 

lub jeśli ciąg zawiera podwójną cytat: –

file="Dr" A.tif" echo $file Dr" A.tif 

W sieci są dobre samouczki na temat znaków specjalnych i cytowania. Zacznij od tego .

Odpowiedź

Nie „Nie musisz zmieniać znaczenia nazw plików obsługiwanych w skrypcie. Zmiana znaczenia jest konieczna tylko wtedy, gdy chcesz umieścić nazwę pliku jako literał w skrypcie lub przekazać kilka nazw plików jako jedną strumień wejściowy do innego skryptu.

Ponieważ „ponownie przeglądasz wyjście find, to to jeden z najprostszych sposobów (!) obsługi każdej możliwej ścieżki :

while IFS= read -r -d "" do file_namex="$(basename -- "$REPLY"; echo x)" file_name="${file_namex%$"\nx"}" do_something -- "$file_name" done <(find "$some_path" -exec printf "%s\0" {} +) 

Odpowiedź

szybka i (bardzo) nieprzyjemna

find . | sed "s/^/"/" | sed "s/$/"/" 

Odpowiedź

Wiele z tych odpowiedzi, w tym ta z największą liczbą głosów przy użyciu printf "%q", nie działa we wszystkich przypadkach bez dodatkowej manipulacji.Proponuję następujący (przykład poniżej):

cat <<EOF; 2015-11-07T03:34:41Z app[postgres.0000]: [TAG] text-search query doesn"t contain lexemes: "" EOF

Komentarze

  • Wybacz pytanie n00b, ale czy możesz wyjaśnić, w jaki sposób faktycznie użyłbyś tego do zmiany znaczenia znaków w ciągu? Jeśli skopiuję kod, który piszesz do mojego terminala, po prostu drukuje 2015-11-07T03: 34: 41Z app [postgres.0000]: [TAG] zapytanie tekstowe nie ' t zawierają leksemy: " " … nic nie jest zmieniane.
  • To ' dosłownie, wszystkie znaki specjalne interpretowane jako znaki dosłowne, a nie ze względu na ich specjalne znaczenie. Spróbuj zamiast tego echo " powyższy ciąg ", aby zobaczyć różnicę.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *