Discussion:
skrypt bash pod Qnap TS-431X2
(Wiadomość utworzona zbyt dawno temu. Odpowiedź niemożliwa.)
Marcin Debowski
2022-12-17 02:14:55 UTC
Permalink
Skrypczę ostatnio pod Qnapowskim Linuksem aby ułatwić sobie życie i
natrafiłem na pozornie trywialny problem zmiany pierwszej litery na dużą.

Powłoką jest bash GNU bash, version 3.2.57(2)-release
(arm-unknown-linux-gnueabihf) i takie operacje jak np.:

na ww. nie działa:
NN="banana"; echo "${NN[@]^}"
banana

Co gorsze, sed jest też przerobiony (i sporo innych) i takie coś:
echo "banana"| sed 's/^\(.\)/\U\1/g'

nie zadziała.

tr też nie działa
echo "banana"| tr '[:lower:]' '[:upper:]'
banana

Jakimś cudem awk działa
echo "banana" | awk '{print toupper(substr($0, 1, 1)) substr($0, 2)}'
Banana

ale wolałbym nie używać zewnętrznych poleceń.

Jakieś pomysły jak to zrobić na stringach pod gołym bashem (pierwszy
przykład), czy dla ver<4 się po prostu nie da?
--
Marcin
Jarosław Sokołowski
2022-12-17 10:27:06 UTC
Permalink
aby ułatwić sobie życie i natrafiłem na pozornie trywialny
problem zmiany pierwszej litery na dużą.
Powłoką jest bash GNU bash, version 3.2.57(2)-release
[...]
tr też nie działa
echo "banana"| tr '[:lower:]' '[:upper:]'
banana
Wygląda jakby działał, bo nie zgłasza błędu, tylko te argumenty
do niego nie przemawiają. Ja bym przetestował to tak:

tr a-z A-Z
tr abn ABN
--
Jarek
Marcin Debowski
2022-12-18 00:58:58 UTC
Permalink
Post by Jarosław Sokołowski
aby ułatwić sobie życie i natrafiłem na pozornie trywialny
problem zmiany pierwszej litery na dużą.
Powłoką jest bash GNU bash, version 3.2.57(2)-release
[...]
tr też nie działa
echo "banana"| tr '[:lower:]' '[:upper:]'
banana
Wygląda jakby działał, bo nie zgłasza błędu, tylko te argumenty
To są jak podejrzewam mocno zmodyfikowane standardowe narzędzia. Ma to
nawet pewne aspekty humorystyczne:

[~] # sed --version
This is not GNU sed version 4.0
Post by Jarosław Sokołowski
tr a-z A-Z
[~] # echo "banana"|tr a-z A-Z
BANANA
Post by Jarosław Sokołowski
tr abn ABN
[~] # echo "banana"|tr abn ABN
BANANA

Dzięki, wolę to niż awk

[~] # N="banana";echo `echo ${N:0:1}|tr a-z A-Z`${N:1}
Banana
--
Marcin
Marcin Debowski
2022-12-18 07:55:52 UTC
Permalink
Przy okazji jakby mi ktoś mógł wytłumaczyć, bo nie mogę wygóglać...

Plik na dysku" Chomik\ Syryjski

Taka konstrukcja:
(1)

for file in *
zwraca wartość w file "Chomik Syryjski"

ale:
(2)

fl=`ls -1`
for file in $fl

zwraca Chomik a Syryjski dopiero w kolejnej iteracji, czyli spacja jest
uznawana za separator listy. Dlaczego dla (1) nie?

A dalej, jak zrobić, żeby koniec lini był takim separatorem, czyli, żeby
lista z ls -1 czy np. find . była separowana po liniach a nie po spacjach?
--
Marcin
Kamil Jońca
2022-12-18 08:18:20 UTC
Permalink
Post by Marcin Debowski
Przy okazji jakby mi ktoś mógł wytłumaczyć, bo nie mogę wygóglać...
Plik na dysku" Chomik\ Syryjski
(1)
for file in *
zwraca wartość w file "Chomik Syryjski"
(2)
fl=`ls -1`
for file in $fl
zwraca Chomik a Syryjski dopiero w kolejnej iteracji, czyli spacja jest
uznawana za separator listy. Dlaczego dla (1) nie?
Strzelam: w (1) * jest przetwarzana przez bash i on 'wie' że to jest
jedna nazwa pliku. W (2) na zmienną przypisujesz kolejne linie mogące zawierać
spacje, ale dla bash to już jest, well, ciąg lini (niektóre ze spacjami)
- i on tak to traktuje, bez zastanawiania się czy to pliki czy może
nazwy filmów.

zobacz co będzie
IFS="
"
fl=`ls -1`
for file in $fl

(to IFS zawiera znak nowej linii)
Post by Marcin Debowski
A dalej, jak zrobić, żeby koniec lini był takim separatorem, czyli, żeby
lista z ls -1 czy np. find . była separowana po liniach a nie po spacjach?
Notabene, uważałbym z podejściem:
for q in *
przy długiej liście plików może ci się wyłożyć

lepiej
find ... -exec {} \;
lub ls |xargs czy find ..|xargs
KJ
--
http://wolnelektury.pl/wesprzyj/teraz/
Marcin Debowski
2022-12-18 10:44:42 UTC
Permalink
Post by Kamil Jońca
Post by Marcin Debowski
Przy okazji jakby mi ktoś mógł wytłumaczyć, bo nie mogę wygóglać...
Plik na dysku" Chomik\ Syryjski
(1)
for file in *
zwraca wartość w file "Chomik Syryjski"
(2)
fl=`ls -1`
for file in $fl
zwraca Chomik a Syryjski dopiero w kolejnej iteracji, czyli spacja jest
uznawana za separator listy. Dlaczego dla (1) nie?
Strzelam: w (1) * jest przetwarzana przez bash i on 'wie' że to jest
jedna nazwa pliku. W (2) na zmienną przypisujesz kolejne linie mogące zawierać
spacje, ale dla bash to już jest, well, ciąg lini (niektóre ze spacjami)
- i on tak to traktuje, bez zastanawiania się czy to pliki czy może
nazwy filmów.
zobacz co będzie
IFS="
"
fl=`ls -1`
for file in $fl
(to IFS zawiera znak nowej linii)
tzn. w sensie:
fl="
jeden dwa
trzy cztery
etc etc"

?

Traktuje spacje i końce linie równorzędnie, tj. daje
jeden
dwa
trzy
cztery
etc
etc
Post by Kamil Jońca
Post by Marcin Debowski
A dalej, jak zrobić, żeby koniec lini był takim separatorem, czyli, żeby
lista z ls -1 czy np. find . była separowana po liniach a nie po spacjach?
Wygląda, że tak się nie da.
Post by Kamil Jońca
for q in *
przy długiej liście plików może ci się wyłożyć
lepiej
find ... -exec {} \;
lub ls |xargs czy find ..|xargs
Jo, to było tylko z oszczędności ilustracyjnej :)
--
Marcin
Jarosław Sokołowski
2022-12-18 11:44:08 UTC
Permalink
Post by Marcin Debowski
Post by Kamil Jońca
zobacz co będzie
IFS="
"
fl=`ls -1`
for file in $fl
(to IFS zawiera znak nowej linii)
[...]
Post by Marcin Debowski
Traktuje spacje i końce linie równorzędnie
No to tak:

IFS=$
--
Jarek
Marcin Debowski
2022-12-18 12:28:21 UTC
Permalink
Post by Marcin Debowski
Post by Kamil Jońca
zobacz co będzie
IFS="
"
fl=`ls -1`
for file in $fl
(to IFS zawiera znak nowej linii)
[...]
Post by Marcin Debowski
Traktuje spacje i końce linie równorzędnie
IFS=$
Wy tu zakładacie, że ja kumam na jakimś rozsądnym poziomie, a to jest
niekoniecznie poprawne założenie :) Dopiero powtórzenie Jarka mnie
zastanowiło, że to musi być jakaś specjalna zmienna.

No działa
IFS="
"
Dzięki :)
--
Marcin
Kontynuuj czytanie narkive:
Loading...