1 hónappal ezelőtt Ubuntu 20.04-en és 18.04-en jelenleg is:
echo "30.1 32.3 0.0 0.0 0.0 16.4" | awk '{for( x=(NF); x>=2; x--) if($x!=0.0) print $x;}'
16.4
32.3
Ez az elvárt működés.
Ugyanaz a parancs Ubuntu 20.04-en jelenleg:
echo "30.1 32.3 0.0 0.0 0.0 16.4" | awk '{for( x=(NF); x>=2; x--) if($x!=0.0) print $x;}'
16.4
0.0
0.0
0.0
32.3
Ez már nem jó, a nullákat nem kéne, hogy kiírja... wtf?
Már nem fut le a scriptem normálisan, ami egy hónapja még működött. Megváltozott az if szintaktikája az awk-ban?
- 794 megtekintés
Hozzászólások
awk, mawk vagy gawk fut éppen nálad awk néven?
- A hozzászóláshoz be kell jelentkezni
Nem említettem, mert Ubuntu default:
$ awk -W version
mawk 1.3.4 20200120
- A hozzászóláshoz be kell jelentkezni
$ sudo apt install gawk
és jó lesz.
$ awk --version
GNU Awk 5.0.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)
- A hozzászóláshoz be kell jelentkezni
Nemtom mi a default, de nalam (Ubuntu 20.04) gawk van (es mukodik jol a fenti), nem hiszem, hogy valaha kezzel alitottam volna ezt. Viszont 18.04-rol update-eltem, lehet, hogy ez szamit.
- A hozzászóláshoz be kell jelentkezni
Tedd idézőjelbe a 0.0-t. Szerintem numerikusan 0-vá konvertálódik az egyik helyen, míg a másikon nem, és ezért. Az awk-ban is vannak típusok, csak nem tűnik fel az automatikus konverzió miatt.
typeof(x) Return a string indicating the type of x. The string will
be one of "array", "number", "regexp", "string", "strnum",
"unassigned", or "undefined".
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Még ezt is nézd meg:
strtonum(str) Examine str, and return its numeric value. If
str begins with a leading 0, treat it as an
octal number. If str begins with a leading 0x
or 0X, treat it as a hexadecimal number. Oth‐
erwise, assume it is a decimal number.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Nekem megy így:
ice@ubuntu:~/.ssh$ cat /etc/issue
Ubuntu 20.04 LTS \n \l
ice@ubuntu:~/.ssh$ echo "30.1 32.3 0.0 0.0 0.0 16.4" | awk '{for( x=(NF); x>=2; x--) if($x != "0.0") print $x;}'
16.4
32.3
- A hozzászóláshoz be kell jelentkezni
Így működik, de egyrészt én numerikus összehasonlítást szeretnék, másrészt meg lehet, hogy 50 másik helyen is megváltozott a program működése? Nem akarom én átírni, meg debugolni, ha eddig jó volt.
Engem az érdekelne, hogy mi változott meg és miért. Na meg, hogy a kód átírása nélkül újra működjön.
- A hozzászóláshoz be kell jelentkezni
$ mawk -W version
mawk 1.3.4 20190203
Copyright 2008-2018,2019, Thomas E. Dickey
Copyright 1991-1996,2014, Michael D. Brennan
random-funcs: arc4random_stir/arc4random
regex-funcs: internal
compiled limits:
sprintf buffer 8192
maximum-integer 2147483647
$ echo $LANG
hu_HU.UTF-8
$ echo "30.1 32.3 0.0 0.0 0.0 16.4" | mawk '{for( x=(NF); x>=2; x--) if($x!=0.0) print $x;}'
16.4
0.0
0.0
0.0
32.3
$ ( LANG=C ; export LANG ; echo "30.1 32.3 0.0 0.0 0.0 16.4" | mawk '{for( x=(NF); x>=2; x--)
16.4
32.3
$
- A hozzászóláshoz be kell jelentkezni
Lokalizacio? Tizedespont helyett tizedesvesszo valamiert? Hasznalj igazi lokalizaciot (LANG=C) minden kritikus dologhoz.
- A hozzászóláshoz be kell jelentkezni
$ LC_ALL=hu_HU.UTF-8 ; echo "30.1 32.3 0.0 0.0 0.0 16.4" | awk '{for( x=(NF); x>=2; x--) if($x!=0.0) print $x;}'
16.4
0.0
0.0
0.0
32.3
$ LC_ALL=C ; echo "30.1 32.3 0.0 0.0 0.0 16.4" | awk '{for( x=(NF); x>=2; x--) if($x!=0.0) print $x;}'
16.4
32.3
- A hozzászóláshoz be kell jelentkezni
Nálam mind a kettőnél ugyanúgy kiírja a nullákat... :(
- A hozzászóláshoz be kell jelentkezni
Nálam:
$ awk --version
awk version 20121220 (FreeBSD)
- A hozzászóláshoz be kell jelentkezni
Már feljebb írtam, hogy nálam mawk 1.3.4.
A másik gépen, amin jól működik meg: mawk 1.3.3. (Ubuntu 18.04)
- A hozzászóláshoz be kell jelentkezni
( Legalább egy export LANG ; -ot mondj még az echo előtt! És ha nem akarod elbarmolni a környezetedet, akkor az egész sort rakd ( ) közé. Ugyanis baromira shell függő, hogy mi történik egy exportált változóval, ha az export után új értéket kap. )
Amúgy szerintem is lokalizációs gondnak tűnik.
- A hozzászóláshoz be kell jelentkezni
( LANG=C ; export LANG ; echo "30.1 32.3 0.0 0.0 0.0 16.4" | awk '{for( x=(NF); x>=2; x--) if($x!=0.0) print $x;}' )
Így működik.
De eddig működött így is:
$ echo $LANG
hu_HU.UTF-8
És a 18.04-es gépen szintén működik most is. Szóval a rejtély még nincs teljesen megoldva.
- A hozzászóláshoz be kell jelentkezni
Nem lehet, hogy az Ubuntunál rájöttek, hogy Magyarországon tizedesvessző van, nem pedig tizedespont? Aztán jött egy frissítés...
Szerk.: Azt sohasem értettem, amikor megvan a megoldás, és továbbra megy az értetlenkedés, hogy ez pontosan úgy legyen jó, ahogy eddig. Akkor pontosan azt a rendszert használd frissítetlenül, mint amelyikkel jó volt.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Az lehet, de akkor meg ennek kéne működnie, nem?
$ echo "30,1 32,3 0,0 0,0 0,0 16,4" | awk '{for( x=(NF); x>=2; x--) if($x!=0,0) print $x;}'
awk: line 1: syntax error at or near ,
Elfogadom a változást, ha tényleg ez a megoldás és direkt csinálták, nem regresszió. De mondjuk ha nem major verzió váltásról van szó, akkor csak nem kellene, hogy elromoljon egy script.
- A hozzászóláshoz be kell jelentkezni
OFF:
mióta van, hogy a mawk a default AWK az Ububan? Meg mernék esküdni rá, hogy régebben valamelyik GAWK verziót adták. - Bár a net szerint már 14.04-ben is mawk volt. Amúgy nem lehet, hogy a volt a 20.04-ben awk verzió frissítés ebben az elmúlt egy hónapban?
/OFF
sudo update-alternatives --config awk
Esetleg?
- A hozzászóláshoz be kell jelentkezni
A /var/log/apt/ könyvtárban lévő history logok szerint nem volt awk frissítés mostanában.
- A hozzászóláshoz be kell jelentkezni
mawk (1.3.4.20200120-2) unstable; urgency=high
* debian/copyright: Refresh dates.
* debian/watch: Add watch file to monitor upstream releases.
-- Boyuan Yang <byang@debian.org> Sun, 16 Feb 2020 14:41:09 -0500
mawk (1.3.4.20200120-1) unstable; urgency=medium
* Upload to unstable.
-- Boyuan Yang <byang@debian.org> Tue, 28 Jan 2020 11:27:10 -0500
mawk (1.3.4.20200120-1~exp1) experimental; urgency=medium
* New upstream release snapshot.
* debian/copyright: Update copyright year information.
* debian/upstream/metadata: Add metadata: Repository,
Repository-Browse.
-- Boyuan Yang <byang@debian.org> Sat, 25 Jan 2020 18:09:03 -0500
mawk (1.3.4.20190203-1~exp1) experimental; urgency=medium
* New upstream release snapshot (Closes: #554167)
+ Fixes segmentation fault on certain awk file.
(Closes: #901477)
+ Fixes crashes with long strings. (Closes: #173664)
+ Fixes bugs around substr. (Closes: #649147)
* debian/control:
+ Declare autopkgtest as test suite. (Closes: #692662)
+ Bump Standards-Version to 4.5.0.
+ Update the pre-depends field and use ${misc:Pre-Depends}
instead.
* debian/copyright: Refresh information.
* debian/: Lintian warning fixes:
- description-synopsis-starts-with-article
[ Adreas Henriksson ]
* debian/patches: Review and drop all obsolete patches.
* Fix up autopkgtest for new version of mawktest.
* debian/control: Use autoconf-dickey instead of mainline
autoconf. This is required for mawk and other programs
maintained upstream by Dickey.
-- Boyuan Yang <byang@debian.org> Sat, 25 Jan 2020 17:50:25 -0500
- A hozzászóláshoz be kell jelentkezni
Ez januári update. A scriptem május elején még lefutott.
Meg ebben a logban mi utal ilyesmi változtatásra?
- A hozzászóláshoz be kell jelentkezni
Szerintem eleve nem jó a scripted. Nekem ez nem tetszik:
if($x!=0.0)
Mert ez numerikus 0, és szerintem implementáció kérdése, hogy a 0, 0.0, 0.00, 0x00, 00 közül mindegyik, vagy csak egyesek felelnek meg az egyenlőségnek. Jó, a 0x00 lehet, hogy csak strtonum() hívását követően lesz nulla. Szóval, ha számként nullát akarnék, akkor 0-t írnék, nem kell bele pont. Ha meg stringként, akkor "0.0" a megoldás. Így mindenképp zavaró.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Ha 0.0 helyett 0 van, akkor se jó. Ha meg 0.0-át nem szabad odaírni, akkor 16.4-et sem? Mert azzal sem jó.
Meg az x változónak nem szabad felvennie a 0.0 értéket numerikus összehasonlítás előtt?
- A hozzászóláshoz be kell jelentkezni
Erről beszélek:
awk 'BEGIN {if (0 == 0.0) printf("true\n"); else printf("false\n");}'
true
awk 'BEGIN {if ("0" == "0.0") printf("true\n"); else printf("false\n");}'
false
awk --version | head -n1
GNU Awk 5.0.1, API: 3.0 (GNU MPFR 4.0.2-p7, GNU MP 6.1.2)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
A 16.4 egy szám, ami egyenlő 16.4-del, vagy például16.400-del is például. Viszont stringként a "16.4" nem lesz egyenlő "16.400"-zal, mert van ott még két darab '0', azaz 0x30 kódú karakter.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Én ezt értem, de itt szó sincs stringként való összehasonlításról. Nem értem, hogy kanyarodtunk ide.
Ez az eredeti probléma:
mawk Ubuntu 20.04:
$ awk 'BEGIN { x=12.3; if(x==12.3) printf("true\n"); else printf("false\n");}'
true
$ echo "12.3" | awk '{ if($1==12.3) printf("true\n"); else printf("false\n"); }'
false
mawk Ubuntu 18.04:
$ awk 'BEGIN { x=12.3; if(x==12.3) printf("true\n"); else printf("false\n");}'
true
$ echo "12.3" | awk '{ if($1==12.3) printf("true\n"); else printf("false\n"); }'
true
gawk Ubuntu 20.04:
$ awk 'BEGIN { x=12.3; if(x==12.3) printf("true\n"); else printf("false\n");}'
true
$ echo "12.3" | awk '{ if($1==12.3) printf("true\n"); else printf("false\n"); }'
true
Miért false a második? Illetve ha elfogadjuk, hogy false a második, akkor miért true az első?
Bugos a mawk vagy nem?
- A hozzászóláshoz be kell jelentkezni
Próbáld meg ezt mawk Ubuntu 20.04 környezetben, kíváncsi vagyok az eredményre:
echo "12,3" | awk '{ if($1==12.3) printf("true\n"); else printf("false\n"); }'
Szerintem true lesz.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
True. :)
Mit csinál az a pipe....? 1 hónapja még nem csinálta? Gawk-nál miért nem probléma most se?
- A hozzászóláshoz be kell jelentkezni
Miközben reggeliztem, majd megcsináltam a fahéjas gyömbér teámat, megértettem a jelenséget. :)
A mawk interpreteren belül a kódra nézvést nincs lokalizáció. Szépen is néznénk ki, ha a környezeti változóktól függene, amit a scriptben leírsz. Tehát ott a 12.3 egy szám, bármi is legyen a lokalizáció. Ezzel szemben az input - és vélelmezem, egy printf("%.2f") esetén az output is, bár nem biztos - feldolgozása a lokalizációs függvények hívásán keresztül történik. Azaz 12,3 egy szám, de más lokalizációval 12.3 egy szám.
Amikor az inputod "0.0" volt, s összehasonlítottad 0.0-val, akkor a magyar lokalizáció szerint ezt nem lehetett számmá konvertálni, így "0.0" string lett belőle. Az összehasonlításkor leírt 0.0 konstans előbb numerikus 0-vá konvertálódott, majd, hogy ne legyen type mismatch, kénytelen lett "0" stringgé konvertálódni. Így a programodban az if("0.0" != "0") hajtódott végre, ami true, s ezért írta végül ki a "0.0"-t.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Nekem akkor is új, hogy a pipe bármit is változtasson a tartalmon, amit átirányít...
- A hozzászóláshoz be kell jelentkezni
Ugye láttad, hogy az echo paraméterében vessző volt a "tizedespont" ?
(Szóval a pipe semmit nem változtat, de ahogy a kollága írja, valószínűleg a magyar lokalizációval megadott törtet a "valódi" 12.3 -ra átalakítja az input során, ami nyilván megegyezik a 12.3-mal.)
- A hozzászóláshoz be kell jelentkezni
Láttam, azért kérdezem, hogy mióta nyúl bele a pipe a tartalomba... duh.
Olyan nincs, hogy "semmit nem változtat" és "de átalakítja az input során". Vagy ez vagy az. Milyen alapon alakítja át? Nem excel az. Legközelebb a 10.15.2018-at fogja átalakítani 2018-10-15-re?
Ugyanakkor gawk:
$ echo "12,3" | awk '{ if($1==12.3) printf("true\n"); else printf("false\n"); }'
false
Újra kérdezem:
- Ha mawk van, akkor a pipe átalakítja a vesszőt ponttá lokalizáció szerint? Ha gawk van, akkor meg nem. Akkor pont, hogy a ponttal működik. Megnézi a pipe, hogy mi jön utána és aszerint alakítgat? Le van ez valahova írva?
Ha a pipe alakítgatna, akkor ugyanaz lenne a mawk és a gawk működése, nem?
- 1 hónapja még a mawk is működött ponttal. Mi változott?
- A hozzászóláshoz be kell jelentkezni
Az alanyt értetted félre, nem az echo vagy a pipe alakít át bármit is, hanem maga az awk.
- A hozzászóláshoz be kell jelentkezni
A pipe bitre pontosan azt viszi át, amit kell. A mawk az, amelyik a környezeti változótól függően vagy 12.3, vagy 12,3 alakban várja az inputben a tizedes törteket. Ha a lokalizációd szerint tizedesvesszőt vár, miközben tizedesponttal kínálod meg, ezt nem fogja számként értelmezni, hanem azt mondja, akkor ez bizony egy string. Az összehasonlítás másik operandusa egy szám volt. Stringet számmal nem lehet összehasonlítani, a string operandust nem lehet számmá alakítani, így az egyetlen lehetőség, hogy a szám operandust konvertálta stringgé, majd utána végezte el az összehasonlítást. Igen ám, de a "0.0" és a "0" stringek valóban nem azonosak. Már a hosszuk is különbözik. Emiatt teljesült a != feltétel, s írta ki, amit nem szerettél volna.
A gawk szerintem egész egyszerűen nem foglalkozik az inputban a számok lokalizációjával. Ebben az értelemben éppen az mawk a fejlettebb.
A megoldás tehát az, ahogy írtam is, hogy a mawk-t a megfelelő környezeti változó megadását követően hívod meg.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Nem barmolom el a környezetet, ui. tcsh a default shell és csak azon belül indítottam egy sh-t.
- A hozzászóláshoz be kell jelentkezni
Csak megerositeskeppen, GNU Awk hasznalataval az elso peldadban szereplo modon megy, minden Linuxomon az van (megneztem), de meg FBSD-n is ezt az eredmenyt adja.
- A hozzászóláshoz be kell jelentkezni
Megerősítve.
- A hozzászóláshoz be kell jelentkezni
A scripted így is működne:
echo "30.1 32.3 0.0 0.0 0.0 16.4" | tr '.' ',' | awk '{for( x=(NF); x>=2; x--) if($x!=0.0) print $x;}'
Persze a helyes megoldás nem ez, hanem a lokalizáció idomitása az inputodhoz:
echo "30.1 32.3 0.0 0.0 0.0 16.4" | LC_ALL=C awk '{for(x = (NF); x >= 2; x--) if($x != 0) print $x;}'
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
TL;DR Kimaradt valamelyik profile-ból a LC_NUMERIC=C
- A hozzászóláshoz be kell jelentkezni