- Lua นำเสนอการควบคุมแบบน้ำหนักเบา พกพาสะดวก และขั้นสูง (โคโรทีน ฟังก์ชันชั้นยอด) เมื่อเปรียบเทียบกับแนวทางการประสานงานของ Bash
- Bash โดดเด่นในด้านท่อและยูทิลิตี้ POSIX ส่วน Lua โดดเด่นเมื่อตรรกะมีความซับซ้อนหรือข้ามแพลตฟอร์ม
- Mako Server และ luash ขยาย Lua เพื่อการทำงานอัตโนมัติในทางปฏิบัติ (os.execute, io.popen) โดยไม่สูญเสียความเรียบง่าย
- ข้อผิดพลาดเช่นทางออก 127 มักเกิดจากนามแฝง/เส้นทางที่ไม่สอดคล้องกัน ตรวจสอบด้วยประเภท -ay สำหรับเส้นทางแบบสัมบูรณ์
การทำงานอัตโนมัติและการเขียนสคริปต์เป็นเรื่องปกติในระบบ Unix และระบบที่คล้าย Unix รวมถึงสภาพแวดล้อมแบบผสมผสานกับ Windows ด้วยการเปรียบเทียบระหว่าง Bash และ Luaเกิดขึ้นอยู่เสมอเมื่อเราต้องการหาจุดสมดุลระหว่างความเร็ว ความสามารถในการพกพา และความง่ายในการบำรุงรักษา
โดยอ้างอิงจากแหล่งข้อมูลชั้นนำ—บทความที่นำเสนอLua ในฐานะทางเลือกที่หลากหลายแทน Bash , คู่มือการใช้งาน Mako Server, การสนทนาในฟอรัม และความคิดเห็นที่สนับสนุน Bash—เราจะจัดระเบียบแนวคิด ยกตัวอย่าง และชี้ให้เห็นข้อผิดพลาดทั่วไป เช่น ข้อผิดพลาดexit 127 ที่น่ากลัว เมื่อเรียกใช้ Lua จาก Bash บน Windows (Git Bash) นอกจากนี้เรายังจะให้บริบทด้วยการอ้างอิงถึงภาษาอื่นๆ ที่ปรากฏในแหล่งข้อมูล (JavaScript, Python, Node.js, HTML5, PHP) และข้อความแจ้งเตือนคุกกี้ของ Reddit ที่หลายคนเห็นเมื่อเปิดกระทู้
Bash และ Lua คืออะไร
กล่าวโดยสรุปBash (Bourne Again Shell) คือเชลล์ที่สำคัญที่สุดสำหรับระบบปฏิบัติการแบบ Unix: มันตีความคำสั่ง จัดการยูทิลิตี้ และอนุญาตให้เชื่อมโยงกระบวนการต่างๆ โดยใช้ไปป์และรีไดเร็กต์วัตถุประสงค์หลักของมันคือการเป็นตัวตีความคำสั่งที่มีประสิทธิภาพ พร้อมด้วยเลเยอร์การเขียนโปรแกรมสำหรับการรวมคำสั่งต่างๆ เข้าด้วยกัน
Luaเป็นภาษาที่มีน้ำหนักเบา รวดเร็ว สามารถฝังตัวได้ ใช้งานได้ข้ามแพลตฟอร์ม และมีไวยากรณ์ที่เรียบง่ายการออกแบบที่เรียบง่ายทำให้สามารถทำงานได้บนทรัพยากรที่จำกัดและภายในแอปพลิเคชันต่างๆ (เช่น เอ็นจิ้นเกม เครื่องมือเครือข่าย เซิร์ฟเวอร์ฝังตัว) โดยมีโครงสร้างการควบคุมที่ทันสมัยและชนิดข้อมูลแบบผสมเพียงชนิดเดียวคือ ตาราง
- ทุบตี:เหมาะอย่างยิ่งสำหรับการประมวลผลข้อความ การจัดการไฟล์ และการดูแลระบบโดยใช้ประโยชน์จากระบบนิเวศทั้งหมดของยูทิลิตี้ POSIX
- Lua: ภาษาสำหรับวัตถุประสงค์ทั่วไป, ฝังได้; ข้อเสนอ การแสดงออกที่มากขึ้น และควบคุมลอจิกที่ซับซ้อน ในขณะที่ยังคงขนาดเล็กและความสามารถในการพกพาสูง
ความแตกต่างที่สำคัญระหว่างสคริปต์และการทำงานอัตโนมัติ
หลายรายการในการจัดอันดับเน้นย้ำจุดนี้: Lua โดดเด่นในเรื่องความเบาและความเร็ว VM ของมันมีขนาดกะทัดรัด และตัวแปลภาษาเริ่มต้นทำงานได้อย่างรวดเร็ว ซึ่งเป็นที่ชื่นชอบในสคริปต์ที่ทำงานหลายครั้ง หรือในสภาพแวดล้อมแบบฝังตัว
ความสามารถในการพกพาเป็นอีกจุดแข็งหนึ่งLua ไม่ได้ผูกติดกับ Unix : มันทำงานได้อย่างราบรื่นบน Linux, macOS และ Windows โดยลดการใช้คำสั่ง `if` ที่เฉพาะเจาะจงกับแพลตฟอร์มให้น้อยที่สุด ในขณะที่ Bash แม้ว่าจะใช้งานได้บน Windows ผ่านโปรแกรมจำลอง (Git Bash, WSL) แต่ ก็ต้อง พึ่งพาเครื่องมือ POSIX และความแตกต่างของสภาพแวดล้อมมากกว่า
ในแง่ของความสามารถในการแสดงออกLua มีฟังก์ชันชั้นเยี่ยมโครูทีน และเมตาเทเบิล เครื่องมือเหล่านี้ช่วยให้คุณสร้างโซลูชันที่ครอบคลุมมากขึ้นโดยไม่ต้องพึ่งพาเครื่องมือภายนอก ในขณะที่ใน Bash มักจะประกอบโซลูชันด้วย sed, awk, grep, find เป็นต้นBash โดดเด่นในระบบนิเวศนั้นและในการทำงานกับไปป์ไลน์
การเรียนรู้และการอ่านออกเขียนได้
คู่มือหลายเล่มชี้ให้เห็นว่าไวยากรณ์ของ Lua คล้ายกับรหัสเทียม (pseudocode) ซึ่งช่วยผู้เริ่มต้นได้ ในทางกลับกัน Bash มีกฎสำหรับการอ้างอิง การขยาย และการแทนที่ที่อาจทำให้ประหลาดใจได้ตัวอย่างที่เทียบเท่ากันสองตัวอย่าง (วนลูปจาก 1 ถึง 5):
# Bash
#!/usr/bin/env bash
for i in {1..5}; do
echo 'Hola, mundo '"$i"
done
-- Lua
for i = 1, 5 do
print('Hola, mundo ' .. i)
end
เวอร์ชัน Lua นั้นตรงไปตรงมาและมีโอกาสเกิดข้อผิดพลาดน้อยกว่าเนื่องจากการอ้างอิงหรือการขยายตัวที่ผิดปกติ ใน Bash การเรียนรู้ว่าจะใช้เครื่องหมายคำพูดเดี่ยว/คู่เมื่อใด และวิธีการขยายตัวของตัวแปรหรือวงเล็บปีกกาเป็นสิ่งสำคัญอย่างยิ่ง
คุณสมบัติ Lua ขั้นสูงสำหรับการทำงานอัตโนมัติ
ฟังก์ชันระดับเฟิร์สคลาส : ฟังก์ชันเหล่านี้ถูกจัดเก็บไว้ในตัวแปร ส่งผ่านเป็นอาร์กิวเมนต์ และส่งกลับ ซึ่งช่วยส่งเสริมความเป็นโมดูลและการนำกลับมาใช้ใหม่ในระบบอัตโนมัติที่มีความซับซ้อนระดับปานกลางถึงสูง
โครูทีน (Coroutines) : ช่วยให้สามารถทำงานพร้อมกันได้โดยไม่ปิดกั้น โดยไม่ต้องจัดการกับเธรดของระบบปฏิบัติการ มีประโยชน์อย่างมากในการประสานงานเวิร์กโฟลว์ (เช่น งาน I/O หลายงาน) โดยไม่เพิ่มความซับซ้อน
เมตาเทเบิลและเมตาเมธอด : ช่วยให้สามารถกำหนดพฤติกรรมของการดำเนินการบนตารางใหม่ได้ ซึ่งเป็นการขยายภาษาเพื่อให้ปรับให้เข้ากับขอบเขตของปัญหา
ตัวอย่างง่ายๆ ที่มักถูกอ้างถึงในบทความ: การประมวลผลไฟล์ทีละบรรทัดในภาษา Lua ด้วยวิธีที่กระชับและชัดเจน:
-- Lua: leer y procesar un archivo línea a línea
local function procesar(archivo)
local f = io.open(archivo, 'r')
for linea in f:lines() do
print('Procesando: ' .. linea)
end
f:close()
end
procesar('ejemplo.txt')
รูปแบบนี้แสดงให้เห็นว่าLua ผสานการรับส่งข้อมูลแบบง่าย ๆ เข้ากับความชัดเจนได้ อย่างไร และสามารถขยายเพื่อใช้ในการแยกวิเคราะห์ กรอง หรือสื่อสารกับส่วนประกอบอื่น ๆ ได้อย่างง่ายดาย
Lua ในทางปฏิบัติ: Mako Server สำหรับการเขียนสคริปต์สมัยใหม่
หนึ่งในคู่มือที่มีคะแนนสูงสุดแนะนำให้ใช้Mako Serverเพื่อขยายขีดความสามารถของ Lua ด้วย API ที่เน้นการทำงานอัตโนมัติ (รวมถึงการเชื่อมต่อเครือข่าย) ลดการพึ่งพาแพ็กเกจภายนอกตัวอย่างคำสั่งทั่วไปจะเป็นดังนี้:
#!/usr/bin/env mako
print('Hola Lua!')
การติดตั้งบน Linux x86-64 (ตามคู่มือ): รวดเร็วและง่ายดาย
cd /tmp
wget makoserver.net/download/mako.linux-x64.tar.gz
tar xvzf mako.linux-x64.tar.gz
sudo cp mako mako.zip /usr/local/bin/
เมื่อติดตั้งเสร็จแล้ว สคริปต์จะทำงานตามปกติและใช้ประโยชน์จาก API เพิ่มเติมของ Makoตัวอย่างเช่น การสร้างเส้นทางและการแสดงรายการเนื้อหาด้วยการเรียกใช้ระบบ:
#!/usr/bin/env mako
os.execute('mkdir -p api/os api/fs')
os.execute('ls -lh api')
หากคุณต้องการใช้งานฟังก์ชันของ Bash (เช่น การขยายคีย์) คุณสามารถเรียกใช้จาก Lua ได้โดยยังคงรักษารูปแบบการใช้งานไว้ได้:
#!/usr/bin/env mako
local function ex(cmd)
-- Usa bash como login shell y escapa el comando
return os.execute('/bin/bash -lc ' .. string.format('%q', cmd))
end
ex('mkdir -p api/{os,fs}')
ex('ls -lh api')
io.popen มีประโยชน์มาก ในการดึงเอาเอาต์พุตมาตรฐาน (ไม่ใช่แค่รหัสการออก) มาใช้ รูปแบบทั่วไปคือการดึงเวอร์ชันไบนารี:
#!/usr/bin/env mako
local function ex(cmd)
local p = io.popen(cmd)
local out = p:read('*a') or ''
p:close()
return (out:gsub('%s+$',''))
end
local function version(s)
return s:match('([%d]+%.[%d]+%.[%d]+)')
end
local nodev = version(ex('node --version'))
print('node version\t' .. (nodev or 'not installed'))
local wgetv = version(ex('wget -V'))
print('wget version\t' .. (wgetv or 'not installed'))
นี่คือวิธีการสร้างการตรวจสอบการพึ่งพาแบบง่ายๆโดยไม่ต้องออกจากภาษา Lua ซึ่งจะช่วยรักษาขั้นตอนการทำงานที่ชัดเจนและพกพาได้สะดวก
แพ็คเกจภายนอกพร้อม Mako: ตัวอย่างพร้อม luash
อีกหนึ่งคำแนะนำยอดนิยมคือluashซึ่งเป็นไลบรารีขนาดเล็กที่ช่วยให้การเรียกใช้คำสั่งระบบจาก Lua ทำได้ง่ายขึ้น ด้วย API ที่คล้ายกับเชลล์การติดตั้งโดยทั่วไป :
git clone https://github.com/zserge/luash.git
sudo mkdir -p /usr/local/share/lua/5.4/
sudo cp luash/sh.lua /usr/local/share/lua/5.4/
สคริปต์สั้นๆ ที่แสดงรายการไดเร็กทอรีปัจจุบันจะมีลักษณะดังนี้ โดยผสมผสานภาษา Lua แบบดั้งเดิมเข้ากับการเรียกใช้คำสั่งแบบเชลล์:
#!/usr/bin/env mako
require('sh')
local cwd = tostring(pwd())
print('Files in ' .. cwd)
local listing = tostring(ls('.'))
for f in listing:gmatch('[^\n]+') do
print(f)
end
แนวคิดคือการลดขั้นตอนการเชื่อมต่อด้วยตนเองให้น้อยที่สุด เมื่อสิ่งที่คุณต้องการคือการเรียกใช้เครื่องมือภายนอกและประมวลผลผลลัพธ์ด้วยความสะดวกสบายของภาษา Lua
Bash หรือ Lua? เกณฑ์การเลือกปฏิบัติ
ความคิดเห็นทั่วไปในฟอรัมต่างๆ คือการวิจารณ์ Bash ว่าไม่ใช่ภาษาโปรแกรมอเนกประสงค์นั้นเป็นการมองข้ามประเด็นสำคัญ Bash ถูกออกแบบมาให้เป็นตัวแปลคำสั่งสำหรับประกอบยูทิลิตี้ของระบบ ภาษาของมันถูกใช้เพื่อเชื่อมต่อยูทิลิตี้เหล่านั้นโดยใช้ไปป์หรือ IPC
หากงานของคุณเกี่ยวข้องกับคอนโซลเป็นอย่างมาก คุณใช้anonymous pipes, redirects, grep/sed/awkเป็นประจำ และตรรกะของคุณไม่ต้องการการประมวลผลจากภายนอกมากนัก Bash ก็ยังคงเป็นเครื่องมืออเนกประสงค์ที่ดีที่สุดมันไม่ได้แข่งขันกับ Lua ในฐานะภาษาโปรแกรมอเนกประสงค์ แต่ Bash สามารถประกอบคำสั่งได้อย่างยอดเยี่ยมกว่าภาษาอื่นๆ
หากกรณีของคุณต้องการการควบคุมการไหลของข้อมูลที่ซับซ้อนการแปลงข้อมูล โครูทีน หรือความสามารถในการพกพาอย่างเคร่งครัด (Linux/macOS/Windows) โดยไม่ต้องพึ่งพาเครื่องมือ POSIX ภาษา Lua จะมอบประสบการณ์ที่สะดวกสบายกว่า ซึ่งช่วยหลีกเลี่ยงความยุ่งยากในการอ้างอิงและการขยายที่ซับซ้อน
สิ่งสำคัญที่ควรจำไว้คือระบบนิเวศ: ด้วย Bash คุณสามารถใช้ประโยชน์จากกลุ่มเครื่องมือ *utils ทั้งหมด (coreutils, binutils, util-linux ฯลฯ) และหากคุณขาดโครงสร้างข้อมูลเฉพาะบางอย่าง ก็มีเครื่องมืออย่างrecutilsที่ช่วยเสริมโมเดลแบบข้อความดั้งเดิมได้
การวินิจฉัยข้อผิดพลาดทั่วไป: กรณีของทางออก 127
ในกระทู้ยอดนิยมกระทู้หนึ่ง การรันสคริปต์เช่นbash bb.shส่งผลให้ได้รหัสข้อผิดพลาด 127หลังจากพยายามใช้คำสั่ง lua -e 'print «hha»'ในขณะที่การรันsource bb.shทำงานได้ปกติ ในระบบ POSIX รหัส 127 หมายถึง “ ไม่พบคำสั่ง ”
หากluaถูกแมปไปยังสิ่งอื่น (ตัวอย่างเช่น ในกระทู้ระบุว่าlua ถูกตั้งชื่อเล่นเป็น `lua53` ) เมื่อเริ่มกระบวนการใหม่ด้วย bash ชื่อเล่นหรือพาธนั้น อาจ ไม่มีอยู่จริง หรืออาจชี้ไปยังไบนารีที่ไม่มีอยู่ใน PATH ที่ใช้งานจริงของซับเชลล์นั้น ทำให้เกิดข้อผิดพลาด 127
ในสภาพแวดล้อม Windows ที่ใช้ Git Bash มีปัจจัยอีกอย่างหนึ่งที่เข้ามาเกี่ยวข้อง: จากcmd.exeเป็นเรื่องปกติที่จะกำหนดdoskey (เช่นdoskey lua=lua53 $* ) หากเซสชัน Git Bash สืบทอดบางอย่างจากสภาพแวดล้อมที่แปลง lua เป็น lua53แต่ lua53 หรือพาธของมันไม่ได้อยู่ในซับเชลล์นั้น คุณจะได้รับข้อผิดพลาด 127 อย่างไรก็ตาม เมื่อคุณรันsourceเชลล์ปัจจุบันที่มีPATH/alias ของตัวเอง จะถูกนำมาใช้ และสามารถทำงานได้
# Comprobar resolución del binario
type -a lua
# Sugerencias:
# 1) Invocar la ruta absoluta: /usr/local/bin/lua o /c/Program Files/lua/lua
# 2) Desactivar alias: unalias lua; o usa 'command lua' para saltarte funciones/alias
# 3) Limpia el hash de rutas en bash: hash -r
# 4) Revisa PATH en el subshell que crea 'bash bb.sh'
วิธีแก้ปัญหาในกรณีนี้คือการลบคำสั่ง`doskey lua=lua53 $*` ออก จากพรอมต์คำสั่ง หลังจากนั้นbash luaก็กลับมาทำงานได้ตามปกติ บทเรียนจากเรื่องนี้คือ: หากคุณเห็นข้อ ผิด พลาด 127 ที่น่าสงสัยให้ตรวจสอบนามแฝง ฟังก์ชันเชลล์ และ PATH ของคุณ และตรวจสอบด้วยคำสั่ง`type -a`หรือ`command -v`ว่าไบนารีใดกำลังพยายามเรียกใช้งานจริง ๆ
บริบท: ภาษาอื่น ๆ และเครื่องมือที่ปรากฏในแหล่งที่มา
ผลลัพธ์ที่ได้ประกอบด้วยคำอธิบายเกี่ยวกับJavaScript (ไม่เฉพาะเวอร์ชันที่ใช้ในเบราว์เซอร์เท่านั้น แต่ยังรวมถึง Node.js/Apache CouchDB ด้วย) และPython (ไวยากรณ์ที่ชัดเจนและใช้งานได้ทั่วไป) ภาษาเหล่านี้มักแข่งขันกันเพื่อแย่งชิงบทบาทในการเขียนสคริปต์อัตโนมัติในทีมที่มีพื้นฐานด้านการพัฒนาซอฟต์แวร์
Node.jsนำเสนอระบบรันไทม์แบบไม่บล็อกสำหรับการประมวลผลแบบเรียลไทม์ ในขณะที่HTML5และPHPกำลังกลายเป็นส่วนประกอบสำคัญของการพัฒนาเว็บในบางหน้าเว็บที่มีการจัดทำดัชนีพวกมันไม่ใช่คู่แข่งโดยตรงกับ Bash หรือ Lua ในด้านการบริหารระบบ แต่เป็นทางเลือกสำหรับการทำงานอัตโนมัติข้ามแพลตฟอร์ม
ในการสนทนามักมีการกล่าวถึงยูทิลิตี้ Python สมัยใหม่ เช่นuvสำหรับแก้ไขปัญหาการพึ่งพาโดยไม่ต้องสร้างโปรเจกต์ขนาดใหญ่ หรือเชลล์ทางเลือกอื่นๆ เช่นxonsh (ที่ใช้ Python เป็นตัวขับเคลื่อน) รวมถึงตัวเลือกอื่นๆ เช่น Racket, D ในโหมดสคริปต์ หรือ OCaml ข้อสรุปในทางปฏิบัติคือ เลือกใช้เครื่องมือตามสถานการณ์เฉพาะและประสบการณ์ของทีมของคุณกับแต่ละระบบนิเวศ
เป็นเรื่องสำคัญที่ควรจำไว้ว่าแพลตฟอร์มโซเชียลอย่างRedditจะแสดงข้อความแจ้งเตือนเกี่ยวกับความเป็นส่วนตัวและคุกกี้ก่อนที่คุณจะสามารถดูเนื้อหาได้ ซึ่งไม่ได้ส่งผลกระทบต่อเทคนิคการใช้งาน แต่เป็นสาเหตุที่ทำให้บางครั้งกระทู้โหลดไม่ขึ้นหากไม่ยอมรับข้อความแจ้งเตือนนั้น
หากคุณต้องการสคริปต์ที่ทำงานได้เหมือนกันทั้งบน Linux, macOS และ Windows พร้อมด้วยตรรกะที่ซับซ้อนการทดสอบที่รวดเร็ว และการประมวลผลที่ฉับไว Lua คือตัวเลือกที่ยอดเยี่ยม แต่หากคุณต้องการจัดการยูทิลิตี้ POSIX เชื่อมต่อเครื่องมือต่างๆ เข้าด้วยกัน และเขียนสคริปต์เชื่อมต่อโดยมีอุปสรรคน้อยที่สุด Bash ก็ยังคงเป็นตัวเลือกที่ไม่มีใครเทียบได้ ข่าวดีก็คือทั้งสองภาษาไม่ได้ขัดแย้งกัน: การผสมผสาน Lua (หรือ Lua+Mako) สำหรับ "ตรรกะ" และ Bash สำหรับ "การเชื่อมต่อเชลล์" จะทำให้คุณได้สิ่งที่ดีที่สุดจากทั้งสองภาษา