Saya memiliki skrip sederhana berikut di mana saya menjalankan loop dan ingin mempertahankan file COUNTER
. Saya tidak dapat mengetahui mengapa penghitung tidak memperbarui. Apakah karena subkulit yang sedang dibuat? Bagaimana cara memperbaikinya?
#!/bin/bash
WFY_PATH=/var/log/nginx
WFY_FILE=error.log
COUNTER=0
grep 'GET /log_' $WFY_PATH/$WFY_FILE | grep 'upstream timed out' | awk -F ', ' '{print $2,$4,$0}' | awk '{print "http://domain.com"$5"&ip="$2"&date="$7"&time="$8"&end=1"}' | awk -F '&end=1' '{print $1"&end=1"}' |
(
while read WFY_URL
do
echo $WFY_URL #Some more action
COUNTER=$((COUNTER+1))
done
)
echo $COUNTER # output = 0
Jawaban:
Pertama, Anda tidak meningkatkan penghitung. Mengubah
COUNTER=$((COUNTER))
menjadiCOUNTER=$((COUNTER + 1))
atauCOUNTER=$[COUNTER + 1]
akan meningkatkannya.Kedua, lebih sulit untuk memperbanyak variabel subkulit ke callee seperti yang Anda duga. Variabel dalam subkulit tidak tersedia di luar subkulit. Ini adalah variabel lokal untuk proses anak.
Salah satu cara untuk mengatasinya adalah dengan menggunakan file temp untuk menyimpan nilai antara:
sumber
$[...]
usang? Apakah ada solusi alternatif?$[...]
digunakanbash
sebelum$((...))
diadopsi oleh shell POSIX. Saya tidak yakin itu pernah secara resmi tidak digunakan lagi, tetapi saya tidak dapat menemukan menyebutkannya dibash
halaman manual, dan tampaknya hanya didukung untuk kompatibilitas ke belakang....
BASH DIUJI: Centos, SuSE, RH
sumber
$[ ]
sintaksnya tidak digunakan lagi. stackoverflow.com/questions/10515964/…adalah konstruksi yang cukup kikuk dalam pemrograman modern.
terlihat lebih "modern". Anda juga bisa menggunakan
jika menurut Anda itu meningkatkan keterbacaan. Kadang-kadang, Bash memberikan terlalu banyak cara untuk melakukan sesuatu - filosofi Perl saya kira - ketika mungkin Python "hanya ada satu cara yang benar untuk melakukannya" mungkin lebih tepat. Itu adalah pernyataan yang bisa diperdebatkan jika memang ada! Bagaimanapun, saya akan menyarankan tujuan (dalam kasus ini) tidak hanya untuk menaikkan variabel tetapi (aturan umum) untuk juga menulis kode yang dapat dipahami dan didukung orang lain. Kesesuaian sangat membantu untuk mencapai itu.
HTH
sumber
Coba gunakan
dari pada
sumber
let "COUNTER++"
(( COUNTER++ ))
(tidak ada tanda dolar)(( COUNTER++ ))
tetapi ketika saya beralih keCOUNTER=$((COUNTER + 1))
sana berhasil.GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Saya rasa satu panggilan awk ini setara dengan
grep|grep|awk|awk
pipeline Anda : silakan coba. Perintah awk terakhir Anda tampaknya tidak mengubah apa pun.Masalah dengan COUNTER adalah perulangan while berjalan dalam subkulit, jadi setiap perubahan pada variabel menghilang ketika subkulit keluar. Anda perlu mengakses nilai COUNTER di subkulit yang sama. Atau ikuti saran @ DennisWilliamson, gunakan substitusi proses, dan hindari subkulit sama sekali.
sumber
sumber
Daripada menggunakan file sementara, Anda dapat menghindari pembuatan subkulit di sekitar
while
loop dengan menggunakan substitusi proses.Ngomong-ngomong, Anda harus bisa mengubah semua itu
grep, grep, awk, awk, awk
menjadi satuawk
.Dimulai dengan Bash 4.2, ada file
lastpipe
opsi itusumber
lastpipe
. Omong-omong, Anda mungkin harus menggunakan"${PIPESTATUS[@]}"
(di alih-alih tanda bintang).minimalis
sumber
Ini semua yang perlu Anda lakukan:
Berikut kutipan dari Learning the bash Shell , Edisi ke-3, hlm. 147, 148:
..........................
Lihat http://www.safaribooksonline.com/a/learning-the-bash/7572399/
sumber
if
pernyataan:if [[ $((needsComma++)) -gt 0 ]]; then printf ',\n'; fi
Benar atau salah, ini adalah satu-satunya versi yang bekerja dengan andal.i=1; while true; do echo $((i++)); sleep .1; done
if (( needsComma++ > 0 )); then
atauif (( needsComma++ )); then
Ini adalah contoh sederhana
sumber
Tampaknya Anda tidak memperbarui
counter
skrip is, gunakancounter++
sumber
Ada dua kondisi yang menyebabkan ekspresi
((var++))
gagal untuk saya:Jika saya menyetel bash ke mode ketat (
set -euo pipefail
) dan jika saya memulai kenaikan saya dari nol (0).Memulai dari satu (1) tidak masalah, tetapi nol menyebabkan kenaikan menghasilkan "1" saat mengevaluasi "++" yang merupakan kegagalan kode pengembalian bukan nol dalam mode ketat.
Saya bisa menggunakan
((var+=1))
atauvar=$((var+1))
menghindari perilaku inisumber
Skrip sumber memiliki masalah dengan subkulit. Contoh pertama, Anda mungkin tidak membutuhkan subkulit. Tapi Kami tidak tahu apa yang tersembunyi di bawah "Beberapa tindakan lagi". Jawaban paling populer memiliki bug tersembunyi, yang akan meningkatkan I / O, dan tidak akan berfungsi dengan subkulit, karena memulihkan couter di dalam loop.
Jangan menambahkan tanda '\', ini akan menginformasikan juru bahasa bash tentang kelanjutan baris. Saya harap ini akan membantu Anda atau siapa pun. Tapi menurut saya skrip ini harus sepenuhnya dikonversi ke skrip AWK, atau ditulis ulang ke python menggunakan regexp, atau perl, tetapi popularitas perl selama bertahun-tahun menurun. Lebih baik lakukan dengan python.
Versi yang Dikoreksi tanpa subkulit:
Versi dengan subkulit jika benar-benar dibutuhkan
sumber