kondisi canggung benar dan salah

9

Saya menemukan bahwa jika kita menggunakan awk 0 inputfile, itu tidak akan mencetak apa pun karena 0berarti kondisi yang salah.

Jika kita gunakan awk 1 inputfile, itu akan mencetak segala sesuatu sebagai 1benar untuk setiap baris penafsiran awk.

Jika kita menggunakan awk any_string inputfile, itu tidak akan mencetak apa-apa karena semua variabel awk diinisialisasi sebagai nol sehingga salah.

Tetapi jika kita gunakan awk any_integer inputfile, itu akan menjadi benar dan mencetak setiap baris file, bolehkah saya tahu apa alasannya?

Saya tidak dapat menemukan ini telah dijelaskan dalam manual GNUawk .

Sylye
sumber
3
oleh any_integerSaya kira Anda berarti jumlah literal seperti 7, 89dll .. jika demikian, alasannya adalah setiap angka selain 0sarana truekondisi
Sundeep

Jawaban:

13

True for awk adalah string yang tidak kosong atau angka yang tidak nol (dengan angka menjadi bilangan bulat desimal atau floating point dan dengan beberapa implementasi awk yang didukung juga heksadesimal atau oktal). Hal-hal yang dilampirkan dalam tanda kutip ganda adalah string, angka literal yang tidak dikutip adalah angka, tetapi untuk hal lain, ada aturan kompleks untuk menentukan apakah sesuatu harus diperlakukan sebagai string atau angka. awkManual GNU memiliki seluruh bab tentang itu .

Benar:

  • awk '1' (angka bukan nol)
  • awk '1e8' (angka bukan nol)
  • awk '-0.01' (angka bukan nol)
  • awk '"foo"' (string tidak kosong)
  • awk '"0"' (string tidak kosong)
  • awk '0 ""' (Rangkaian menghasilkan string yang di sini tidak kosong)
  • echo 0 | awk '$1 ""' (sama untuk bidang $ n)
  • awk 'substr("000", 1, 1)'(hasil substr()selalu berupa string)
  • echo '0foo' | awk '$0' ($ 0 adalah string non-numerik sehingga dianggap sebagai string (non-kosong))

Salah:

  • awk '0' (0 angka)
  • awk '""' (string kosong)
  • echo 0000e123 | awk '$1' ($ 1 dianggap angka jika itu adalah string numerik yang ada di sini dan menjadi 0)
  • echo ' 0 ' | awk '$0' (spasi awal dan akhir diabaikan untuk menentukan apakah string numerik).
  • awk '" 2foo" - 2' (string yang terlibat dalam ekspresi aritmatika dikonversi ke angka dengan apapun yang melewati angka tersebut diabaikan)
  • awk 'unset_or_empty_variable' (string kosong)
  • awk '"non-numerical-string" + 0'

YMMV:

  • awk '1e-500' (beberapa akan mengeluh, beberapa akan memperlakukannya sebagai 0)
  • awk '"0x1" + 0'(tidak semua implementasi awk mendukung heksadesimal, pada yang "0x1"dikonversikan ke 1, pada yang lain ke 0. Beberapa versi spesifikasi POSIX secara tidak sengaja memerlukan implementasi untuk mendukung nomor heksadesimal di sana dan telah ditarik kembali nanti. Masih gawkmengenali nomor hex ketika POSIXLY_CORRECTada di lingkungan)
  • awk '010 - 8' (sama (juga tidak cukup seperti 010 adalah literal di sini sebagai lawan dikonversi dari string) untuk oktal)
  • awk '0x1 - 1'(pada awkimplementasi yang tidak mendukung angka hex, 0x1adalah gabungan dari 0dan x1variabel yang menghasilkan "0"yang dikonversi ke angka (0), jika Anda mengurangi 1Anda mendapatkan -1yang bukan angka nol).

Apa artinya itu adalah bahwa jika Anda ingin memeriksa apakah string tidak kosong, Anda tidak boleh melakukannya:

awk '$ 1 {print $ 1, "tidak kosong"}'

Tapi

awk '$1 != "" {print $1, "is not empty"}'

Kalau tidak, itu tidak akan mengatakan 0atau -0000E+00001234tidak kosong.

Stéphane Chazelas
sumber
Jawabannya mengesankan dan detail! Namun satu pertanyaan: pada contoh terakhir yang Anda berikan, saya memang mencoba sintaksnya dan yang pertama berhasil, di mana ia melompati $ 1 yang kosong dan hanya mencetak baris itu dengan $ 1 non kosong, karena jika $ 1 kosong maka akan menjadi Salah, dan karenanya tidak mencetak hasilnya, bukan?
sylye