⌨️ sed, awk, curl and > on a Mac · sed, awk, curl และ > บนแมค · 在 Mac 上用 sed、awk、curl 和 >

Five tools, already on your Mac. Fetch a real price, change it, count it, keep it. Nothing to install. Seven challenges at the end. · ห้าเครื่องมือ ที่มีอยู่ในแมคของคุณแล้ว ไปเอาราคาจริงมา แก้มัน นับมัน เก็บมันไว้ ไม่ต้องติดตั้งอะไร ปิดท้ายด้วยโจทย์เจ็ดข้อ · 五个工具,你的 Mac 上已经有了。取一个真实价格,改它、数它、留住它。什么都不用装。最后有七道题。

🇬🇧 English

Five things live in the Terminal. You already have all of them.

| joins two programs. > sends the answer to a file. curl fetches from the internet. sed changes text. awk counts columns.

This page uses all five on one real price. By the end you have a log that grows every day.

🇹🇭 ไทย

มีห้าอย่างอยู่ในเทอร์มินัล คุณมีครบทุกอันอยู่แล้ว

| ต่อสองโปรแกรมเข้าด้วยกัน > ส่งคำตอบลงไฟล์ curl ไปเอาของจากอินเทอร์เน็ต sed แก้ข้อความ awk นับคอลัมน์

หน้านี้ใช้ทั้งห้าอย่างกับราคาจริงหนึ่งราคา จบแล้วคุณจะได้บันทึกที่ยาวขึ้นทุกวัน

🇨🇳 中文

终端里住着五样东西。你已经全都有了。

| 把两个程序接起来。> 把答案送进文件。curl 从网上取东西。sed 改文字。awk 数列。

这一页用这五样东西对付一个真实价格。到最后你会有一份每天变长的记录。

By handทำด้วยมือ用手做With these fiveด้วยห้าอย่างนี้用这五样
Where the answer goesคำตอบไปอยู่ที่ไหน答案去哪了the screen, then goneขึ้นจอ แล้วก็หายไป屏幕上,然后就没了a file you keepไฟล์ที่คุณเก็บไว้ได้一个你留得住的文件
Getting data from a siteเอาข้อมูลจากเว็บ从网站上拿数据open it, copy, pasteเปิด ก๊อป วาง打开、复制、粘贴one curl linecurl บรรทัดเดียว一行 curl
Changing a thousand linesแก้พันบรรทัด改一千行you edit each oneคุณแก้ทีละบรรทัด你一行一行改sed does it oncesed ทำครั้งเดียวจบsed 一次就做完
Adding up a columnบวกตัวเลขทั้งคอลัมน์把一列加起来you find a calculatorคุณไปหาเครื่องคิดเลข你去找个计算器awk already knowsawk รู้อยู่แล้วawk 本来就会
OPEN THE TERMINAL APP FIRST Press Command and Space. Type Terminal. Press Enter. Your Mac shows a % sign, not a $. Both mean the same thing: type here. Every tool on this page is already installed. You do not need Homebrew. กด Command กับ Space พิมพ์ Terminal แล้วกด Enter แมคของคุณจะขึ้นเครื่องหมาย % ไม่ใช่ $ ทั้งสองอันหมายถึงอย่างเดียวกัน คือพิมพ์ที่นี่ ทุกเครื่องมือในหน้านี้ติดตั้งมาให้แล้ว คุณไม่ต้องใช้ Homebrew 按 Command 加 Space,输入 Terminal,按回车。你的 Mac 显示的是 %,不是 $。两个的意思一样:在这里打字。这一页的每个工具都已经装好了。你不需要 Homebrew。

➡️ Tutorial 1 — Two signs do most of the work · บทที่ 1 — เครื่องหมายสองตัวทำงานเกือบทั้งหมด · 教程 1 —— 两个符号干掉大半活

🇬🇧 English

Before any tool, learn where the answer goes. That is what > and | decide.

Learn these two and every other command gets easier.

🇹🇭 ไทย

ก่อนจะรู้จักเครื่องมือใด ให้รู้ก่อนว่าคำตอบไปไหน นั่นคือสิ่งที่ > กับ | ตัดสิน

เรียนสองอันนี้ แล้วคำสั่งอื่นจะง่ายขึ้นทั้งหมด

🇨🇳 中文

在认识任何工具之前,先搞清楚答案去哪。那是 > 和 | 决定的事。

学会这两个,别的命令都会变简单。

1 > keeps the answer in a file · > เก็บคำตอบไว้ในไฟล์ · > 把答案留在文件里

🇬🇧 English

Most commands print to the screen. The screen forgets. A file does not.

> makes a new file. >> adds to the end of one. Type these four lines in order.

🇹🇭 ไทย

คำสั่งส่วนใหญ่พิมพ์ขึ้นจอ จอลืมได้ แต่ไฟล์ไม่ลืม

> สร้างไฟล์ใหม่ >> ต่อท้ายไฟล์เดิม พิมพ์สี่บรรทัดนี้ตามลำดับ

🇨🇳 中文

大多数命令都打到屏幕上。屏幕会忘,文件不会。

> 造一个新文件。>> 接在旧文件后面。把这四行按顺序打进去。

⌨️ TYPE THESE · one line at a time

# > makes the file. If it was there already, the old one is gone.
echo "Hello, Chiang Mai" > hello.txt
cat hello.txt

# >> adds a line. It never throws anything away.
echo "Second line" >> hello.txt
cat hello.txt

# One > again, and both old lines are gone. No warning.
echo "This wipes it" > hello.txt
cat hello.txt

🖥️ WHAT IT PRINTED

Hello, Chiang Mai
Hello, Chiang Mai
Second line
This wipes it
LineWhat it does · ทำอะไร · 做什么
echo "Hello, Chiang Mai"Prints words. On its own it goes to the screen.พิมพ์คำออกมา ถ้าอยู่เฉย ๆ มันจะไปขึ้นจอ把字打出来。单独用就打到屏幕上。
> hello.txtSends it to the file instead. The screen stays empty.ส่งมันลงไฟล์แทน จอจะว่างเปล่า改送进文件里。屏幕上什么都没有。
cat hello.txtShows what is in a file. Good for checking your work.แสดงว่าในไฟล์มีอะไร ใช้ตรวจงานของตัวเองได้ดี显示文件里有什么。用来检查自己做对没有。
>> hello.txtAdds to the end. Two arrows keep, one arrow wipes.ต่อท้ายไฟล์ สองลูกศรคือเก็บ ลูกศรเดียวคือล้าง加在末尾。两个箭头是留,一个箭头是清。
ONE ARROW DESTROYS THE FILE, AND NEVER ASKS There is no "are you sure?" There is no Trash. The old file is simply gone. This is the most expensive typo at the terminal. Read the arrow twice before you press Enter. When you mean to add, two arrows. ไม่มีคำถามว่า "แน่ใจไหม" ไม่มีถังขยะ ไฟล์เดิมหายไปเลย นี่คือการพิมพ์ผิดที่แพงที่สุดในเทอร์มินัล อ่านลูกศรสองครั้งก่อนกด Enter ถ้าคุณจะต่อท้าย ให้ใช้สองลูกศร 不会问"你确定吗"。也没有废纸篓。旧文件就这样没了。这是终端里最贵的一个打字失误。按回车前把箭头看两遍。想加东西,就用两个箭头。
YOUR TURN
  1. Run all four lines. Watch hello.txt change.
  2. Add three more lines with >>. Then cat it.
  3. Now use one >. Count what is left.
  4. Try date > today.txt. Then cat today.txt.
  1. รันทั้งสี่บรรทัด แล้วดู hello.txt เปลี่ยนไป
  2. เพิ่มอีกสามบรรทัดด้วย >> แล้ว cat ดู
  3. ทีนี้ใช้ > อันเดียว นับดูว่าเหลืออะไร
  4. ลอง date > today.txt แล้ว cat today.txt
  1. 四行都跑一遍,看 hello.txt 怎么变。
  2. 用 >> 再加三行,然后 cat 一下。
  3. 现在用一个 >。数数还剩什么。
  4. 试 date > today.txt,再 cat today.txt。

2 Errors come out of a second pipe · ข้อผิดพลาดออกมาอีกท่อหนึ่ง · 报错走的是第二根管子

🇬🇧 English

Every command has two exits. Good output leaves by one. Errors leave by the other.

> only catches the good one. Errors need 2>. That is why an error still shows on screen.

🇹🇭 ไทย

ทุกคำสั่งมีทางออกสองทาง ผลลัพธ์ที่ดีออกทางหนึ่ง ข้อผิดพลาดออกอีกทาง

> รับแค่ทางที่ดี ข้อผิดพลาดต้องใช้ 2> เพราะแบบนี้ข้อผิดพลาดจึงยังขึ้นจออยู่

🇨🇳 中文

每个命令都有两个出口。好结果从一个出来,报错从另一个出来。

> 只接好的那个。报错要用 2>。所以报错还是会出现在屏幕上。

⌨️ TYPE THESE

# Make one real file, so one name works and one does not.
printf 'one\ntwo\n' > hello.txt

# cat reads both names. The good text goes left, the complaint goes right.
cat hello.txt missing.txt > found.txt 2> problems.txt

cat found.txt
cat problems.txt

# 2>&1 means: send the errors down the same pipe as the good output.
cat hello.txt missing.txt > both.txt 2>&1
cat both.txt

🖥️ WHAT IT PRINTED · found.txt, then problems.txt, then both.txt

one
two
cat: missing.txt: No such file or directory
one
two
cat: missing.txt: No such file or directory
LineWhat it does · ทำอะไร · 做什么
printf 'one\ntwo\n'Like echo, but \n means a new line. Useful for test files.คล้าย echo แต่ \n คือขึ้นบรรทัดใหม่ เหมาะกับไฟล์ทดลอง和 echo 差不多,但 \n 表示换行。做测试文件很好用。
> found.txtCatches only what worked. The error is not in here.รับแค่ส่วนที่สำเร็จ ข้อผิดพลาดไม่ได้อยู่ในนี้只接成功的那部分。报错不在这里面。
2> problems.txtCatches only the complaints. The 2 is the error exit.รับแค่ข้อผิดพลาด เลข 2 คือทางออกของข้อผิดพลาด只接抱怨的话。那个 2 就是报错的出口。
2>&1Puts both in one file. Read it as: exit 2 joins exit 1.เอาทั้งสองใส่ไฟล์เดียว อ่านว่า ทางออก 2 ไปรวมกับทางออก 1两个都放进一个文件。读作:出口 2 汇入出口 1。
WHY TWO EXITS AT ALL Because you often want to keep the data and read the trouble. Send the data to a file. Let the errors stay on screen. You see problems at once. Your file stays clean. เพราะบ่อยครั้งคุณอยากเก็บข้อมูลไว้ แต่อยากอ่านปัญหาด้วย ส่งข้อมูลลงไฟล์ ปล่อยให้ข้อผิดพลาดค้างอยู่บนจอ คุณจะเห็นปัญหาทันที และไฟล์ของคุณก็ไม่มีขยะปน 因为你常常想把数据留下,同时又想看到问题。数据送进文件,报错留在屏幕上。你马上看得见问题,文件里也不会混进垃圾。
YOUR TURN
  1. Run it. Open both files. Note which line went where.
  2. Drop the 2> part. The error is back on screen.
  3. Try cat missing.txt 2> /dev/null. It is silent now.
  4. /dev/null is the bin. Nothing written there comes back.
  1. รันดู เปิดทั้งสองไฟล์ ดูว่าบรรทัดไหนไปอยู่ที่ไหน
  2. ตัดส่วน 2> ออก ข้อผิดพลาดจะกลับมาขึ้นจอ
  3. ลอง cat missing.txt 2> /dev/null ทีนี้มันเงียบ
  4. /dev/null คือถังขยะ อะไรที่เขียนลงไปจะไม่กลับมา
  1. 跑一遍。两个文件都打开。看哪一行去了哪里。
  2. 把 2> 那段去掉。报错又回到屏幕上了。
  3. 试 cat missing.txt 2> /dev/null。现在它安静了。
  4. /dev/null 就是垃圾桶。写进去的东西回不来。

3 | joins two programs together · | ต่อสองโปรแกรมเข้าด้วยกัน · | 把两个程序接起来

🇬🇧 English

> sends output to a file. | sends it to another program.

That is the whole idea of the terminal. Small tools, joined in a line. Each one does one job well.

🇹🇭 ไทย

> ส่งผลลัพธ์ลงไฟล์ | ส่งมันไปให้อีกโปรแกรม

นั่นคือแนวคิดทั้งหมดของเทอร์มินัล เครื่องมือเล็ก ๆ ต่อกันเป็นแถว แต่ละอันทำงานเดียวให้ดี

🇨🇳 中文

> 把输出送进文件。| 把它送给另一个程序。

这就是终端的全部想法。小工具,排成一行接起来。每个只把一件事做好。

⌨️ TYPE THESE

# tr swaps one character for another. Here: every space becomes a new line.
echo "one two three" | tr ' ' '\n'

# Now add sort. Three words, one per line, in order.
echo "banana apple cherry" | tr ' ' '\n' | sort

# And wc -l counts the lines it was given.
echo "banana apple cherry" | tr ' ' '\n' | sort | wc -l

🖥️ WHAT IT PRINTED

one
two
three
apple
banana
cherry
3
LineWhat it does · ทำอะไร · 做什么
echo "one two three" |The words never reach the screen. They go to tr instead.คำพวกนี้ไม่เคยไปถึงจอ มันไปหา tr แทน这些字根本没到屏幕上。它们去了 tr 那边。
tr ' ' '\n'Swaps each space for a new line. One word per line now.เปลี่ยนช่องว่างทุกอันเป็นบรรทัดใหม่ ทีนี้หนึ่งคำต่อบรรทัด把每个空格换成换行。现在一行一个词。
| sortSorts the lines it is given. It needs one per line.เรียงบรรทัดที่ได้รับมา มันต้องการหนึ่งอย่างต่อบรรทัด把收到的行排序。它要求一行一个。
| wc -lCounts lines. Three tools in a row, each doing one job.นับบรรทัด สามเครื่องมือเรียงกัน แต่ละอันทำงานเดียว数行数。三个工具排一排,各做一件事。
wc PUTS SPACES IN FRONT OF THE NUMBER ON A MAC On your Mac, wc -l prints the number with spaces before it. You get 3 with padding, not a bare 3. Alone on screen it looks fine. It breaks the moment you compare it to a number. Two fixes: read it with wc -l < file, or pass it through tr -d ' '. บนแมคของคุณ wc -l จะพิมพ์ตัวเลขโดยมีช่องว่างนำหน้า คุณจะได้ 3 ที่มีช่องว่างนำ ไม่ใช่ 3 เปล่า ๆ ถ้าอยู่บนจอเฉย ๆ ก็ดูปกติ แต่มันพังทันทีที่คุณเอาไปเทียบกับตัวเลข แก้ได้สองทาง อ่านด้วย wc -l < file หรือส่งผ่าน tr -d ' ' 在你的 Mac 上,wc -l 打出的数字前面带空格。你拿到的是带空白的 3,不是干净的 3。单独看着没问题,一旦拿去和数字比较就出错。两个办法:用 wc -l < file 读,或者过一道 tr -d ' '。
YOUR TURN
  1. Run all three lines. Watch the pipe grow.
  2. Add | head -2 to the end. Only two lines now.
  3. Try ls /usr/bin | wc -l. Your Mac has a lot.
  4. Now ls /usr/bin | sort | head -3. The first three.
  1. รันทั้งสามบรรทัด ดูท่อยาวขึ้นเรื่อย ๆ
  2. เติม | head -2 ท้ายสุด ทีนี้เหลือสองบรรทัด
  3. ลอง ls /usr/bin | wc -l แมคของคุณมีเยอะ
  4. แล้วลอง ls /usr/bin | sort | head -3 จะได้สามอันแรก
  1. 三行都跑。看这根管子越接越长。
  2. 末尾加 | head -2。现在只剩两行。
  3. 试 ls /usr/bin | wc -l。你的 Mac 里有不少。
  4. 再试 ls /usr/bin | sort | head -3。头三个。

🌐 Tutorial 2 — curl goes and gets it · บทที่ 2 — curl ไปเอามาให้ · 教程 2 —— curl 去把它取回来

🇬🇧 English

curl is a browser with no window. You give it an address. It brings back the text.

From here on the page uses one real address. It is the price of bitcoin in Thai baht.

🇹🇭 ไทย

curl คือเบราว์เซอร์ที่ไม่มีหน้าต่าง คุณให้ที่อยู่ไป มันเอาข้อความกลับมา

จากนี้ไปหน้านี้จะใช้ที่อยู่จริงอันหนึ่ง มันคือราคาบิตคอยน์เป็นเงินบาท

🇨🇳 中文

curl 是一个没有窗口的浏览器。你给它地址,它把文字带回来。

从这里开始,这一页只用一个真实地址。它是比特币的泰铢价格。

4 One real price, on your screen · ราคาจริงหนึ่งราคา บนจอของคุณ · 一个真实价格,出现在你屏幕上

🇬🇧 English

Bitkub is a Thai exchange. It answers anyone, with no key and no sign-up.

The answer is JSON. It is one long line. Every number arrives as text, inside quotes.

🇹🇭 ไทย

Bitkub คือตลาดซื้อขายของไทย มันตอบทุกคน ไม่ต้องมีคีย์ ไม่ต้องสมัคร

คำตอบเป็น JSON มันคือบรรทัดยาวบรรทัดเดียว ตัวเลขทุกตัวมาเป็นข้อความ อยู่ในเครื่องหมายคำพูด

🇨🇳 中文

Bitkub 是泰国的一家交易所。它回答任何人,不用密钥,不用注册。

答案是 JSON。就一条长长的行。每个数字都以文字形式出现,包在引号里。

⌨️ TYPE THIS

# -s means silent. Without it curl draws a progress bar over your answer.
curl -s "https://api.bitkub.com/api/v3/market/ticker?sym=BTC_THB"

# The same line again, kept in a file this time.
curl -s "https://api.bitkub.com/api/v3/market/ticker?sym=BTC_THB" > price.json
cat price.json

🖥️ WHAT IT PRINTED · the real answer, 27 September 2026

[{"symbol":"BTC_THB","base_volume":"23.16745634","high_24_hr":"2824252","highest_bid":"2818749.1","last":"2818749.09","low_24_hr":"2799000","lowest_ask":"2819502.68","percent_change":"0.59","quote_volume":"65094106.59"}]
LineWhat it does · ทำอะไร · 做什么
curl -sFetches the address. -s hides the progress bar.ไปเอาจากที่อยู่นั้น -s ซ่อนแถบความคืบหน้า去取那个地址。-s 把进度条藏起来。
"https://...?sym=BTC_THB"Quotes matter. The ? and = confuse the shell without them.เครื่องหมายคำพูดสำคัญ ถ้าไม่มี ? กับ = จะทำให้เชลล์สับสน引号很重要。没有它,? 和 = 会把 shell 搞糊涂。
[{...}]A list with one thing in it. Bitkub always sends a list.ลิสต์ที่มีของอยู่ชิ้นเดียว Bitkub ส่งลิสต์มาเสมอ一个只装了一样东西的列表。Bitkub 总是送列表来。
"last":"2818749.09"The price we want. Note the quotes: this is text, not a number.ราคาที่เราต้องการ สังเกตเครื่องหมายคำพูด นี่คือข้อความ ไม่ใช่ตัวเลข我们要的价格。注意那对引号:这是文字,不是数字。
YOU GET A real price, in a real file, in two lines of typing.ราคาจริง ในไฟล์จริง ด้วยการพิมพ์สองบรรทัด一个真实价格,装在真实文件里,只打了两行字。
YOUR TURN
  1. Run both lines. Your price will differ from ours.
  2. Swap BTC for ETH in the address. Run again.
  3. Drop the -s. See the progress bar get in the way.
  4. Remove the quotes. Read what the shell says.
  1. รันทั้งสองบรรทัด ราคาของคุณจะไม่เหมือนของเรา
  2. เปลี่ยน BTC เป็น ETH ในที่อยู่ แล้วรันอีกที
  3. ตัด -s ออก ดูแถบความคืบหน้ามาเกะกะ
  4. เอาเครื่องหมายคำพูดออก อ่านสิ่งที่เชลล์บอก
  1. 两行都跑。你的价格会和我们的不一样。
  2. 把地址里的 BTC 换成 ETH,再跑一次。
  3. 把 -s 去掉。看进度条怎么挡路。
  4. 把引号去掉。读一下 shell 说了什么。

5 The five flags worth learning · ห้าแฟล็กที่ควรจำ · 值得记住的五个参数

🇬🇧 English

curl has over two hundred flags. Five of them cover most days.

The important one is -f. Without it, a broken page still looks like success.

🇹🇭 ไทย

curl มีแฟล็กมากกว่าสองร้อยตัว ห้าตัวพอใช้ได้เกือบทุกวัน

ตัวที่สำคัญคือ -f ถ้าไม่มีมัน หน้าที่พังก็ยังดูเหมือนสำเร็จ

🇨🇳 中文

curl 有两百多个参数。五个就够应付大多数日子。

关键的是 -f。没有它,一个坏掉的页面看起来也像成功。

Flagแฟล็ก参数What it doesทำอะไร做什么Reach for it whenใช้เมื่อ什么时候用
-sHides the progress barซ่อนแถบความคืบหน้า藏掉进度条always, in a pipeตลอด เมื่ออยู่ในท่อ在管子里,总是要
-SShows errors even when silentแสดงข้อผิดพลาดแม้ตอนเงียบ安静时也把报错说出来always, next to -sตลอด คู่กับ -s总是,跟 -s 一起
-fFails loudly on a 404แจ้งล้มเหลวเสียงดังเมื่อเจอ 404遇到 404 就大声失败any script that must be rightสคริปต์ใดที่ต้องถูกต้อง任何必须正确的脚本
-LFollows a redirectตามการเปลี่ยนเส้นทางไป跟着跳转走the answer looks emptyคำตอบดูว่างเปล่า答案看起来空的
-o nameWrites to a file, like >เขียนลงไฟล์ เหมือน >写进文件,和 > 一样downloading something bigดาวน์โหลดของใหญ่下载大东西

⌨️ TYPE THESE · ask for a coin that does not exist

# Bitkub says error 11. But curl says everything went fine.
curl -s "https://api.bitkub.com/api/v3/market/ticker?sym=NOPE_THB"
echo "exit was $?"

# A page that is really missing. -f makes curl admit it.
curl -sS -f "https://api.bitkub.com/api/v3/market/nothing-here"
echo "exit was $?"

# -w prints one fact you choose. Here: the status number.
curl -s -o /dev/null -w '%{http_code}\n' "https://api.bitkub.com/api/v3/market/ticker?sym=BTC_THB"
curl -s -o /dev/null -w '%{http_code}\n' "https://api.bitkub.com/api/v3/market/nothing-here"

🖥️ WHAT IT PRINTED

{"error":11}
exit was 0
curl: (22) The requested URL returned error: 404
exit was 22
200
404
EXIT 0 MEANS CURL WAS HAPPY, NOT THAT YOU GOT DATA Read the first two lines again. Bitkub said error 11. Nothing useful came back. And curl reported success. It did its job: it delivered the page. What the page said is not its problem. So use -f. Check the exit number too. Skip both and you will log error messages for weeks. อ่านสองบรรทัดแรกอีกครั้ง Bitkub บอกว่า error 11 ไม่มีอะไรที่ใช้ได้กลับมาเลย แต่ curl รายงานว่าสำเร็จ มันทำงานของมันเสร็จ คือส่งหน้าเว็บมาให้ ส่วนหน้านั้นเขียนว่าอะไรไม่ใช่เรื่องของมัน ใช้ -f และตรวจเลขทางออกด้วย ไม่งั้นคุณจะเก็บข้อความผิดพลาดลงไฟล์ข้อมูลไปเป็นสัปดาห์ 再读前两行。Bitkub 说 error 11,什么有用的都没回来。而 curl 报告成功。它把活干完了:它把页面送到了。页面上写什么不是它的事。用 -f,并且检查退出码,否则你会连着好几周把报错存进数据文件里。
YOUR TURN
  1. Run all six lines. Compare the two exit numbers.
  2. $? holds the exit number of the last command.
  3. Try -w '%{time_total}\n'. How slow is Bitkub?
  4. Add --max-time 5. Now a dead site cannot hang you.
  1. รันทั้งหกบรรทัด เทียบเลขทางออกสองตัว
  2. $? เก็บเลขทางออกของคำสั่งล่าสุดไว้
  3. ลอง -w '%{time_total}\n' Bitkub ช้าแค่ไหน
  4. เติม --max-time 5 ทีนี้เว็บที่ตายแล้วจะไม่ทำให้คุณค้าง
  1. 六行都跑。把两个退出码比一比。
  2. $? 装着上一条命令的退出码。
  3. 试 -w '%{time_total}\n'。Bitkub 有多慢?
  4. 加上 --max-time 5。现在死掉的网站卡不住你了。

✂️ Tutorial 3 — sed changes text on the way past · บทที่ 3 — sed แก้ข้อความตอนที่มันไหลผ่าน · 教程 3 —— sed 在文字路过时改它

🇬🇧 English

sed reads one line, changes it, and prints it. Then the next line.

It never opens a window and never asks. Give it a rule and it applies it everywhere.

🇹🇭 ไทย

sed อ่านบรรทัดหนึ่ง แก้มัน แล้วพิมพ์ออกมา จากนั้นก็บรรทัดถัดไป

มันไม่เคยเปิดหน้าต่าง และไม่เคยถาม ให้กฎมันไปหนึ่งข้อ มันจะใช้กฎนั้นทุกที่

🇨🇳 中文

sed 读一行,改它,打出来。然后下一行。

它从不开窗口,也从不问。给它一条规则,它就到处照着做。

6 Swap one word for another · เปลี่ยนคำหนึ่งเป็นอีกคำ · 把一个词换成另一个

🇬🇧 English

One rule does nine tenths of all sed work. It is s/old/new/.

The s means substitute. The slashes are just fences. Add g and it changes every one.

🇹🇭 ไทย

กฎข้อเดียวทำงาน sed ได้เก้าในสิบส่วน คือ s/เก่า/ใหม่/

s คือแทนที่ ขีดทับเป็นแค่รั้วกั้น เติม g แล้วมันจะเปลี่ยนทุกอัน

🇨🇳 中文

一条规则就干掉 sed 九成的活:s/旧/新/。

s 是替换。斜线只是栅栏。加个 g,它就每一个都换。

⌨️ TYPE THESE

# Change one thing. The rest of the line is untouched.
echo "I teach in Chiang Mai" | sed 's/Chiang Mai/Lamphun/'

# Without g, sed changes the first one on the line and stops.
echo "one one one" | sed 's/one/two/'

# With g, it keeps going to the end of the line. g is for global.
echo "one one one" | sed 's/one/two/g'

🖥️ WHAT IT PRINTED

I teach in Lamphun
two one one
two two two
LineWhat it does · ทำอะไร · 做什么
sed 's/old/new/'Four parts: s, the old, the new, and an end fence.สี่ส่วน คือ s ของเก่า ของใหม่ และรั้วปิดท้าย四个部分:s、旧的、新的,还有收尾的栅栏。
's/one/two/'Changes the first match only. Easy to forget.เปลี่ยนแค่อันแรกที่ตรง ลืมกันบ่อย只换第一个匹配的。很容易忘。
's/one/two/g'g for global. Changes every match on the line.g คือ global เปลี่ยนทุกอันที่ตรงในบรรทัดนั้นg 是 global。这一行里每个匹配都换。
single quotesAlways. Double quotes let the shell eat your $ signs.ใช้เสมอ ถ้าใช้เครื่องหมายคำพูดคู่ เชลล์จะกิน $ ของคุณ一律用单引号。双引号会让 shell 把你的 $ 吃掉。
YOUR TURN
  1. Run the three lines. Watch where g matters.
  2. Change your own name into a friend's name.
  3. Try sed 's/a//g'. Every a is gone.
  4. An empty new part deletes. That is a useful trick.
  1. รันสามบรรทัด ดูว่า g สำคัญตรงไหน
  2. เปลี่ยนชื่อของคุณเป็นชื่อเพื่อน
  3. ลอง sed 's/a//g' ตัว a จะหายไปหมด
  4. ถ้าส่วนใหม่ว่างเปล่า คือการลบ เป็นทริกที่ใช้ได้ดี
  1. 三行都跑。看 g 在哪里起作用。
  2. 把你自己的名字换成朋友的名字。
  3. 试 sed 's/a//g'。每个 a 都没了。
  4. 新的那部分留空就是删除。这招很好用。

7 Pull the price out of the JSON · ดึงราคาออกมาจาก JSON · 把价格从 JSON 里抠出来

🇬🇧 English

Now the real job. That JSON line holds nine numbers. You want one.

Two ways. The first uses two easy steps. The second does it in one, with a group.

🇹🇭 ไทย

ทีนี้งานจริง บรรทัด JSON นั้นมีตัวเลขเก้าตัว คุณต้องการตัวเดียว

มีสองวิธี วิธีแรกใช้สองขั้นง่าย ๆ วิธีที่สองทำในขั้นเดียว ด้วยการจับกลุ่ม

🇨🇳 中文

现在是真活了。那行 JSON 里有九个数字,你只要一个。

两个办法。第一个分两步,都很简单。第二个一步搞定,用到一个分组。

⌨️ TYPE THESE

# Way one, in two steps. Cut off the front, then cut off the back.
# .* means "any amount of anything", so this eats everything before the price.
sed 's/.*"last":"//' price.json | sed 's/".*//'

# Way two, in one step. -E turns on groups. The ( ) marks what to keep,
# and \1 means "put group one back here". Everything else is thrown away.
sed -E 's/.*"last":"([0-9.]+)".*/\1/' price.json

🖥️ WHAT IT PRINTED · both ways, same answer

2818749.09
2818749.09
LineWhat it does · ทำอะไร · 做什么
.*"last":"Anything, then the label. Replacing it with nothing cuts the front off.อะไรก็ได้ แล้วตามด้วยป้ายชื่อ แทนที่ด้วยความว่างเปล่าคือตัดส่วนหน้าออก任何东西,然后是那个标签。换成空的就等于把前面剪掉。
's/".*//'From the next quote to the end, gone. The price is left alone.จากเครื่องหมายคำพูดถัดไปจนจบ หายไป เหลือแต่ราคา从下一个引号到结尾,全去掉。只剩价格。
sed -ETurns on groups and +. Works on a Mac and on Linux.เปิดใช้การจับกลุ่มและ + ใช้ได้ทั้งบนแมคและลินุกซ์打开分组和 + 的支持。Mac 和 Linux 上都能用。
([0-9.]+)One or more digits and dots, remembered as group one.ตัวเลขและจุดหนึ่งตัวหรือมากกว่า จำไว้เป็นกลุ่มที่หนึ่ง一个或多个数字和点,记成第一组。
\1Group one, put back. The whole line becomes just that.กลุ่มที่หนึ่ง เอากลับมาวาง ทั้งบรรทัดจะเหลือแค่นั้น第一组,放回来。整行就只剩这个了。
USE -E, NEVER -r, IF YOU WANT IT TO RUN ON A MAC Many tutorials online write sed -r. That is a Linux-only spelling. Your Mac will refuse it. -E means the same thing and works on both. Whenever a copied command fails on your Mac, check for -r first. บทเรียนออนไลน์หลายแห่งเขียน sed -r นั่นเป็นการเขียนแบบลินุกซ์เท่านั้น แมคของคุณจะไม่ยอมรับ -E หมายถึงอย่างเดียวกันและใช้ได้ทั้งสองระบบ ถ้าคำสั่งที่ก๊อปมาใช้ไม่ได้บนแมค ให้ดู -r ก่อนเลย 网上很多教程写 sed -r。那是只有 Linux 才认的写法,你的 Mac 会拒绝。-E 意思一样,两边都能用。抄来的命令在 Mac 上跑不动时,先查有没有 -r。
YOUR TURN
  1. Run both ways. You should get the same number.
  2. Change last to low_24_hr. The day's lowest price.
  3. Change it to percent_change. Watch it break on a minus.
  4. Fix that by writing (-?[0-9.]+) instead.
  1. รันทั้งสองวิธี คุณควรได้ตัวเลขเดียวกัน
  2. เปลี่ยน last เป็น low_24_hr จะได้ราคาต่ำสุดของวัน
  3. เปลี่ยนเป็น percent_change ดูมันพังเมื่อเจอเครื่องหมายลบ
  4. แก้โดยเขียน (-?[0-9.]+) แทน
  1. 两种办法都跑。你应该得到同一个数。
  2. 把 last 改成 low_24_hr。当天最低价。
  3. 再改成 percent_change。看它遇到负号就坏掉。
  4. 改写成 (-?[0-9.]+) 就修好了。

8 Whole lines, and the -i trap · ทั้งบรรทัด และกับดักของ -i · 整行,以及 -i 这个坑

🇬🇧 English

sed also works on whole lines. Print some, delete others.

Then one warning. sed can edit a file in place. On a Mac that flag bites.

So this page changes files another way. It is longer, and it is safe everywhere.

🇹🇭 ไทย

sed ทำงานกับทั้งบรรทัดได้ด้วย พิมพ์บางบรรทัด ลบบางบรรทัด

แล้วมีคำเตือนหนึ่งข้อ sed แก้ไฟล์ทับที่เดิมได้ บนแมคแฟล็กนั้นกัดเจ็บ

🇨🇳 中文

sed 也能对整行下手。印几行,删几行。

然后一句警告。sed 能直接改文件本身。在 Mac 上那个参数会咬人。

⌨️ TYPE THESE

printf 'first\nsecond\nthird\nfourth\n' > lines.txt

# -n tells sed to print nothing on its own. Then p prints what you picked.
sed -n '2p' lines.txt

# Two numbers with a comma is a range.
sed -n '2,3p' lines.txt

# Slashes around a word match it. d deletes those lines.
sed '/second/d' lines.txt

# The portable way to change a file: write a new one, then rename it.
# && means "only if that worked", so a failed sed cannot wipe your file.
sed 's/first/FIRST/' lines.txt > lines.new && mv lines.new lines.txt
head -1 lines.txt

🖥️ WHAT IT PRINTED

second
second
third
first
third
fourth
FIRST
LineWhat it does · ทำอะไร · 做什么
sed -n '2p'Line two only. Without -n you get every line, twice.เฉพาะบรรทัดสอง ถ้าไม่มี -n คุณจะได้ทุกบรรทัด สองรอบ只要第二行。没有 -n 的话每行都会出现两遍。
sed -n '2,3p'A range. Handy for looking inside a very big file.ช่วงบรรทัด สะดวกเวลาอยากส่องดูข้างในไฟล์ใหญ่มาก一个区间。想往超大文件里瞄一眼时很方便。
sed '/second/d'Deletes any line holding that word. The file is untouched.ลบบรรทัดใดที่มีคำนั้น ตัวไฟล์ไม่ถูกแตะ删掉含有那个词的行。文件本身没被动。
> lines.new && mvWrite, then rename. Works on every machine, and you can check it.เขียนก่อน แล้วเปลี่ยนชื่อ ใช้ได้ทุกเครื่อง และตรวจได้ด้วย先写,再改名。每台机器都能用,而且你能检查。
sed -i NEEDS TWO EXTRA QUOTES ON A MAC Linux writes sed -i 's/a/b/' file. Your Mac needs sed -i '' 's/a/b/' file — with an empty pair of quotes. Miss them and your Mac reads the rule as a backup name. You then get a strange file, or an error. Nothing changes where you wanted it to. This is the single most common macOS sed complaint online. The write-then-rename line above avoids all of it. That is what this page teaches. ลินุกซ์เขียน sed -i 's/a/b/' file แมคของคุณต้องใช้ sed -i '' 's/a/b/' file คือมีเครื่องหมายคำพูดเปล่าคู่หนึ่ง ถ้าลืม แมคจะอ่านกฎนั้นเป็นชื่อไฟล์สำรอง คุณจะได้ไฟล์แปลก ๆ หรือข้อความผิดพลาด และไม่มีการแก้ไขตรงที่คุณต้องการ นี่คือเรื่องที่คนบ่นเรื่อง sed บนแมคมากที่สุดในอินเทอร์เน็ต บรรทัดเขียนแล้วเปลี่ยนชื่อข้างบนเลี่ยงปัญหานี้ทั้งหมด หน้านี้จึงสอนแบบนั้นแทน Linux 写 sed -i 's/a/b/' file。你的 Mac 要写 sed -i '' 's/a/b/' file,中间多一对空引号。漏了,Mac 就把那条规则当成备份文件名。于是你得到一个怪文件,或者一条报错,而该改的地方没改。这是网上关于 Mac 上 sed 最常见的抱怨。上面那句先写再改名完全绕开了这场争论,所以这一页教的是那个。
YOUR TURN
  1. Run every line. Check lines.txt at the end.
  2. Drop the -n from the first one. Count the lines.
  3. Delete two words at once with '/second/d; /third/d'.
  4. Try sed -n '$p' lines.txt. $ means the last line.
  1. รันทุกบรรทัด แล้วตรวจ lines.txt ตอนจบ
  2. ตัด -n ออกจากอันแรก แล้วนับบรรทัด
  3. ลบสองคำพร้อมกันด้วย '/second/d; /third/d'
  4. ลอง sed -n '$p' lines.txt เครื่องหมาย $ คือบรรทัดสุดท้าย
  1. 每行都跑。最后检查一下 lines.txt。
  2. 把第一句的 -n 去掉,数数行数。
  3. 用 '/second/d; /third/d' 一次删两个词。
  4. 试 sed -n '$p' lines.txt。$ 是最后一行。

📊 Tutorial 4 — awk thinks in columns · บทที่ 4 — awk คิดเป็นคอลัมน์ · 教程 4 —— awk 是按列来想的

🇬🇧 English

sed sees a line as one piece of string. awk sees columns.

That is the only difference worth remembering. Use sed to change text. Use awk when the data has columns.

🇹🇭 ไทย

sed มองบรรทัดเป็นข้อความก้อนเดียว awk มองเห็นคอลัมน์

นั่นคือข้อต่างเดียวที่ควรจำ ใช้ sed แก้ข้อความ ใช้ awk เมื่อข้อมูลมีคอลัมน์

🇨🇳 中文

sed 把一行看成一整条字串。awk 看到的是列。

这是唯一值得记住的区别。改文字用 sed。数据有列的时候用 awk。

9 $1 is the first word · $1 คือคำแรก · $1 就是第一个词

🇬🇧 English

awk splits every line at the spaces. Then it names the pieces.

$1 is the first. $2 is the second. NF is how many there are, so $NF is the last.

🇹🇭 ไทย

awk ตัดทุกบรรทัดตรงช่องว่าง แล้วตั้งชื่อให้แต่ละชิ้น

$1 คือชิ้นแรก $2 คือชิ้นที่สอง NF คือมีทั้งหมดกี่ชิ้น ดังนั้น $NF คือชิ้นสุดท้าย

🇨🇳 中文

awk 在空格处把每一行切开,然后给每一块起名字。

$1 是第一块。$2 是第二块。NF 是一共有几块,所以 $NF 是最后一块。

⌨️ TYPE THESE

# The braces hold what awk should do with each line.
echo "Nari teaches English in Chiang Mai" | awk '{print $1}'

# A comma between them puts a space between them.
echo "Nari teaches English in Chiang Mai" | awk '{print $1, $NF}'

# NF counts the pieces. Six words, so NF is 6.
echo "Nari teaches English in Chiang Mai" | awk '{print NF}'

🖥️ WHAT IT PRINTED

Nari
Nari Mai
6
LineWhat it does · ทำอะไร · 做什么
awk '{print $1}'The braces run once for each line coming in.วงเล็บปีกกาทำงานหนึ่งรอบต่อทุกบรรทัดที่เข้ามา这对大括号,每进来一行就跑一次。
$1The first piece. awk counts from 1, not from 0.ชิ้นแรก awk นับจาก 1 ไม่ใช่จาก 0第一块。awk 从 1 数起,不是从 0。
$NFThe last piece, without counting them yourself.ชิ้นสุดท้าย โดยที่คุณไม่ต้องนับเอง最后一块,不用你自己数。
print $1, $NFNote "Nari Mai". The last word is Mai, not Chiang Mai.สังเกต "Nari Mai" คำสุดท้ายคือ Mai ไม่ใช่ Chiang Mai注意 "Nari Mai"。最后一个词是 Mai,不是 Chiang Mai。
awk SPLITS AT SPACES, SO A PLACE NAME BECOMES TWO PIECES Look at Nari Mai again. Chiang Mai is one place. awk saw two words. It has no idea what a name is. Does your data have spaces inside a field? Then do not split on spaces. Use a comma or a tab, and tell awk with -F. ดู Nari Mai อีกครั้ง Chiang Mai คือที่เดียว แต่ awk เห็นเป็นสองคำ มันไม่รู้เลยว่าชื่อคืออะไร ถ้าข้อมูลของคุณมีช่องว่างอยู่ในช่อง อย่าตัดที่ช่องว่าง ให้ใช้จุลภาคหรือแท็บแทน แล้วบอก awk ด้วย -F 再看 Nari Mai。Chiang Mai 是一个地方,awk 看成了两个词。它根本不知道什么叫名字。数据的字段里有空格时,就别按空格切。改用逗号或制表符,再用 -F 告诉 awk。
YOUR TURN
  1. Run the three lines. Try $2 and $3 too.
  2. Ask for $9. An empty piece prints nothing.
  3. Try awk '{print $NF, $1}'. The order is yours.
  4. Pipe a real file in: awk '{print $1}' lines.txt.
  1. รันสามบรรทัด ลอง $2 กับ $3 ด้วย
  2. ขอ $9 ดู ชิ้นที่ว่างเปล่าจะไม่พิมพ์อะไรออกมา
  3. ลอง awk '{print $NF, $1}' ลำดับขึ้นอยู่กับคุณ
  4. ส่งไฟล์จริงเข้าไป awk '{print $1}' lines.txt
  1. 三行都跑。$2 和 $3 也试试。
  2. 要一个 $9。空的那块什么都不打。
  3. 试 awk '{print $NF, $1}'。顺序你说了算。
  4. 送一个真文件进去:awk '{print $1}' lines.txt。

10 A table, a filter, and a total · ตาราง ตัวกรอง และผลรวม · 一张表、一个筛选、一个合计

🇬🇧 English

Here is why awk exists. Put a test in front of the braces.

Then awk only acts on lines that pass. And END runs once, after the last line.

🇹🇭 ไทย

นี่คือเหตุผลที่ awk มีอยู่ ใส่เงื่อนไขไว้หน้าวงเล็บปีกกา

แล้ว awk จะทำแค่กับบรรทัดที่ผ่านเงื่อนไข และ END ทำงานหนึ่งครั้ง หลังบรรทัดสุดท้าย

🇨🇳 中文

这就是 awk 存在的理由。在大括号前面放一个条件。

然后 awk 只处理通过条件的行。而 END 在最后一行之后跑一次。

⌨️ TYPE THESE

# Three students. A name, a subject, and a number of lessons.
printf 'Nari,English,12\nSom,Maths,9\nKai,English,15\n' > class.csv

# -F, says the columns are split by commas, not spaces.
awk -F, '{print $1}' class.csv

# A test in front of the braces. Only matching lines get printed.
awk -F, '$2 == "English" {print $1, $3}' class.csv

# total starts at zero on its own. awk does that for you.
awk -F, '{total = total + $3} END {print "total", total}' class.csv

# NR is the row number, so at the END it is the number of rows.
# printf lets you choose the shape. %.1f means one digit after the dot.
awk -F, '{total += $3} END {printf "average %.1f\n", total / NR}' class.csv

🖥️ WHAT IT PRINTED

Nari
Som
Kai
Nari 12
Kai 15
total 36
average 12.0
LineWhat it does · ทำอะไร · 做什么
-F,Split at commas. Now a field may hold a space safely.ตัดที่จุลภาค ทีนี้ช่องหนึ่งจะมีช่องว่างอยู่ได้อย่างปลอดภัย按逗号切。现在字段里可以安心放空格了。
$2 == "English"A test, before the braces. Two equals signs means "is it".เงื่อนไข อยู่หน้าวงเล็บปีกกา เท่ากับสองตัวหมายถึง "ใช่หรือไม่"一个条件,放在大括号前面。两个等号问的是"是不是"。
total = total + $3Runs on every line. total starts empty, which counts as zero.ทำงานทุกบรรทัด total เริ่มจากว่างเปล่า ซึ่งนับเป็นศูนย์每行都跑。total 一开始是空的,算作零。
END {print ...}Runs once, after the last line. This is where answers go.ทำงานครั้งเดียว หลังบรรทัดสุดท้าย คำตอบอยู่ตรงนี้跑一次,在最后一行之后。答案都放这里。
total += $3A short way to write the same thing. Both are fine.วิธีเขียนสั้นของอย่างเดียวกัน ใช้ได้ทั้งคู่同一件事的短写法。两种都行。
NRThe row number. At the END it is the number of rows.เลขแถว ตอน END มันคือจำนวนแถวทั้งหมด行号。到 END 时它就是总行数。
WHEN TO USE WHICH Use sed when you want the same text changed everywhere. Use awk when the data has columns. Use it to count, to filter, or to add up. If you find yourself counting in sed, stop. That is an awk job. ใช้ sed เมื่ออยากเปลี่ยนข้อความเดิมให้เหมือนกันทุกที่ ใช้ awk เมื่อข้อมูลมีคอลัมน์ หรือเมื่อต้องนับ กรอง หรือบวก ถ้าคุณพบว่าตัวเองกำลังนับใน sed ให้หยุด นั่นเป็นงานของ awk 想把同样的文字到处改掉,用 sed。数据有列,或者要数、要筛、要加总,用 awk。如果你发现自己在用 sed 数东西,停下来。那是 awk 的活。
YOUR TURN
  1. Run all five lines. Read each answer.
  2. Add your own students to class.csv with >>.
  3. Change the test to $3 > 10. Busy students only.
  4. Print the highest instead: $3 > best {best = $3}.
  1. รันทั้งห้าบรรทัด อ่านคำตอบแต่ละอัน
  2. เพิ่มนักเรียนของคุณเองใน class.csv ด้วย >>
  3. เปลี่ยนเงื่อนไขเป็น $3 > 10 เอาแค่คนที่เรียนเยอะ
  4. ลองพิมพ์ค่าสูงสุดแทน $3 > best {best = $3}
  1. 五行都跑。每个答案都读一遍。
  2. 用 >> 把你自己的学生加进 class.csv。
  3. 把条件改成 $3 > 10。只看课多的。
  4. 改成打印最大值:$3 > best {best = $3}。

🔗 Tutorial 5 — All five in one line · บทที่ 5 — ห้าอย่างในบรรทัดเดียว · 教程 5 —— 五样东西写在一行里

🇬🇧 English

You now know all five. Here they are in one command, doing real work.

The answer is a file that grows. Run it tomorrow and you have two days.

🇹🇭 ไทย

ตอนนี้คุณรู้จักทั้งห้าอย่างแล้ว นี่คือทั้งห้าในคำสั่งเดียว ที่ทำงานจริง

ผลลัพธ์คือไฟล์ที่ยาวขึ้นเรื่อย ๆ รันอีกทีวันพรุ่งนี้ คุณจะมีสองวัน

🇨🇳 中文

五个你现在都认识了。它们合在一条命令里,干真正的活。

结果是一个会变长的文件。明天再跑一次,你就有两天了。

11 A price log that grows every day · บันทึกราคาที่ยาวขึ้นทุกวัน · 一个每天变长的价格记录

🇬🇧 English

Read the command as five jobs in a row. Each one hands its work to the next.

Only the last part touches the disk. Everything before it is just text moving along.

🇹🇭 ไทย

อ่านคำสั่งนี้เป็นห้างานเรียงกัน แต่ละงานส่งผลให้งานถัดไป

มีแค่ส่วนสุดท้ายที่แตะดิสก์ ทุกอย่างก่อนหน้านั้นเป็นแค่ข้อความที่ไหลผ่าน

🇨🇳 中文

把这条命令读成五件排队的活。每一件把成果交给下一件。

只有最后那部分碰硬盘。它前面的一切都只是文字在往前流。

curlfetch the JSONไปเอา JSON取回 JSON
|hand it onส่งต่อ传下去
sedkeep the priceเก็บแค่ราคา只留价格
awkadd the dateเติมวันที่加上日期
>>append to the logต่อท้ายบันทึก接到记录后面

📄 NEW FILE · log_price.sh

# log_price.sh — one price, one dated line, appended to a log.
# Run it today and tomorrow. The file remembers both.

# A backslash at the end of a line means "this command carries on below".
# Nothing may follow it, not even a space, or the shell ends the line there.
curl -sS -f "https://api.bitkub.com/api/v3/market/ticker?sym=BTC_THB" \
  | sed -E 's/.*"last":"([0-9.]+)".*/\1/' \
  | awk -v day="$(date +%F)" '{printf "%s,%.2f\n", day, $1}' \
  >> price_log.csv

cat price_log.csv

🖥️ WHAT IT PRINTED · one run, 27 September 2026

2026-09-27,2818749.09
LineWhat it does · ทำอะไร · 做什么
curl -sS -fQuiet, but it still shouts if the fetch fails.เงียบ แต่ถ้าดึงไม่สำเร็จมันจะยังส่งเสียง安静,但取失败时它照样会喊。
\ at the endThe command carries on below. Nothing may follow it.คำสั่งต่อในบรรทัดล่าง ห้ามมีอะไรตามหลังมัน命令在下面接着写。后面不能再有任何东西。
| sed -EThrows away everything but the price. One number left.ทิ้งทุกอย่างเหลือแต่ราคา เหลือตัวเลขตัวเดียว除了价格什么都扔掉。只剩一个数。
-v day="$(date +%F)"Hands awk one value from outside. date +%F is today.ส่งค่าหนึ่งค่าจากข้างนอกให้ awk date +%F คือวันนี้从外面递一个值给 awk。date +%F 就是今天。
printf "%s,%.2f\n"Builds the line: text, comma, two decimal places.ประกอบบรรทัดขึ้นมา ข้อความ จุลภาค ทศนิยมสองตำแหน่ง把这行拼出来:文字、逗号、两位小数。
>> price_log.csvTwo arrows. One arrow here would erase yesterday.สองลูกศร ถ้าใช้ลูกศรเดียวตรงนี้จะลบของเมื่อวาน两个箭头。这里用一个箭头就把昨天抹掉了。
YOU GET A dated price log, ready for a spreadsheet. Four lines of shell.บันทึกราคาที่มีวันที่ ในรูปแบบสเปรดชีต จากเชลล์สี่บรรทัด一份带日期的价格记录,表格格式,四行 shell 写成。
SAVE IT AS A FILE, THEN RUN IT WITH sh Use the Download button above to save log_price.sh. Then type sh log_price.sh to run it. You do not need chmod for this. Running it twice on the same day adds the same day twice. Challenge 4 fixes that. ใช้ปุ่มดาวน์โหลดข้างบนเพื่อบันทึก log_price.sh แล้วพิมพ์ sh log_price.sh เพื่อรัน คุณไม่ต้องใช้ chmod สำหรับเรื่องนี้ ถ้ารันสองครั้งในวันเดียวกัน วันนั้นจะถูกเพิ่มสองรอบ โจทย์ข้อ 4 แก้เรื่องนี้ 用上面的下载按钮把 log_price.sh 存下来,然后打 sh log_price.sh 运行它。这件事不需要 chmod。同一天跑两次,那天就会被加两遍。第 4 题解决这个问题。
YOUR TURN
  1. Run it. Then run it again. Two lines now.
  2. Open price_log.csv in Numbers. It is a real spreadsheet.
  3. Change %.2f to %.0f. No decimals now.
  4. Run it once a day for a week. You have a chart.
  1. รันดู แล้วรันอีกที ทีนี้มีสองบรรทัด
  2. เปิด price_log.csv ใน Numbers มันเป็นสเปรดชีตจริง
  3. เปลี่ยน %.2f เป็น %.0f ทีนี้ไม่มีทศนิยม
  4. รันวันละครั้งหนึ่งสัปดาห์ คุณจะได้กราฟ
  1. 跑一次。再跑一次。现在两行了。
  2. 用 Numbers 打开 price_log.csv。它是真的表格。
  3. 把 %.2f 改成 %.0f。现在没有小数了。
  4. 一天跑一次,跑一周。你就有一张图了。

🏆 Tutorial 6 — Seven challenges · บทที่ 6 — โจทย์เจ็ดข้อ · 教程 6 —— 七道题

🇬🇧 English

Each one starts from what you already have. Try it before you open the answer.

Every answer uses only the five tools on this page. Nothing new to install.

🇹🇭 ไทย

ทุกข้อเริ่มจากสิ่งที่คุณมีอยู่แล้ว ลองทำเองก่อนเปิดเฉลย

ทุกเฉลยใช้แค่ห้าเครื่องมือในหน้านี้ ไม่มีอะไรใหม่ที่ต้องติดตั้ง

🇨🇳 中文

每一题都从你已经有的东西出发。先自己试,再打开答案。

每个答案只用这一页的五个工具。没有新东西要装。

12 Try first. The answers are folded away. · ลองเองก่อน เฉลยพับซ่อนไว้ · 先自己试。答案折起来放着。

🇬🇧 English

Click a solution to open it. Each one was run before it was written down here.

🇹🇭 ไทย

คลิกที่เฉลยเพื่อเปิดดู ทุกอันถูกรันจริงก่อนจะถูกเขียนลงตรงนี้

🇨🇳 中文

点一下答案就展开。每一个都是先跑过,才写到这里来的。

1The highest price of the day · ราคาสูงสุดของวัน · 当天的最高价

🇬🇧 English

The same JSON holds high_24_hr. Print only that.

One sed line. You already wrote nearly all of it.

🇹🇭 ไทย

JSON อันเดิมมี high_24_hr อยู่ด้วย พิมพ์ออกมาแค่อันนั้น

sed บรรทัดเดียว คุณเขียนมันไว้เกือบหมดแล้ว

🇨🇳 中文

同一份 JSON 里有 high_24_hr。只把那个打出来。

一行 sed。你差不多已经写过了。

Show the answerดูเฉลย看答案
# Only the label changed. The shape of the rule is the same.
sed -E 's/.*"high_24_hr":"([0-9.]+)".*/\1/' price.json

🖥️ WHAT IT PRINTED

2824252

2Two coins, one file · สองเหรียญ ไฟล์เดียว · 两个币,一个文件

🇬🇧 English

Write both BTC and ETH into one file. Do not type the command twice.

A for loop repeats a command with a different word each time.

🇹🇭 ไทย

เขียนทั้ง BTC และ ETH ลงไฟล์เดียว อย่าพิมพ์คำสั่งเดิมสองครั้ง

ลูป for ทำคำสั่งซ้ำ โดยเปลี่ยนคำไปเรื่อย ๆ

🇨🇳 中文

把 BTC 和 ETH 都写进一个文件。别把命令打两遍。

for 循环把命令重复做,每次换一个词。

Show the answerดูเฉลย看答案
# two_coins.sh — the same four lines, run once per coin.

# Start clean, so running this twice does not double the file.
rm -f two.csv

# sym holds BTC on the first pass, then ETH on the second.
for sym in BTC ETH; do
  curl -sS -f "https://api.bitkub.com/api/v3/market/ticker?sym=${sym}_THB" \
    | sed -E 's/.*"last":"([0-9.]+)".*/\1/' \
    | awk -v coin="$sym" '{printf "%s,%.2f\n", coin, $1}' \
    >> two.csv
done

cat two.csv

🖥️ WHAT IT PRINTED · both coins, live

BTC,2818749.09
ETH,90098.44
LineWhat it does · ทำอะไร · 做什么
for sym in BTC ETH; doRuns the body once per word. sym holds the current one.ทำส่วนในหนึ่งรอบต่อหนึ่งคำ sym เก็บคำปัจจุบันไว้每个词跑一遍里面的内容。sym 装着当前那个。
${sym}_THBThe braces end the name. Without them the shell reads sym_THB.วงเล็บปีกกาปิดท้ายชื่อ ถ้าไม่มี เชลล์จะอ่านเป็น sym_THB大括号把名字收尾。没有它,shell 会读成 sym_THB。
rm -f two.csv-f means do not complain if it is not there yet.-f คือถ้ายังไม่มีไฟล์ ก็ไม่ต้องบ่น-f 的意思是:还没有这个文件也别抱怨。

3Up or down, in words · ขึ้นหรือลง เป็นคำพูด · 涨还是跌,用词说

🇬🇧 English

percent_change can be negative. Print up or down instead of a sign.

Remember the minus. Your rule from step 7 will drop it.

🇹🇭 ไทย

percent_change เป็นลบได้ ให้พิมพ์ up หรือ down แทนเครื่องหมาย

อย่าลืมเครื่องหมายลบ กฎจากขั้นที่ 7 ของคุณจะทำมันหลุด

🇨🇳 中文

percent_change 可能是负的。用 up 或 down 代替符号。

记住那个负号。你第 7 步的规则会把它丢掉。

Show the answerดูเฉลย看答案
# -? in the group means "a minus sign here is allowed, but not required".
sed -E 's/.*"percent_change":"(-?[0-9.]+)".*/\1/' price.json \
  | awk '{ if ($1 > 0) print "up", $1 "%"; else if ($1 < 0) print "down", -$1 "%"; else print "flat" }'

🖥️ WHAT IT PRINTED · the market was up that morning

up 0.59%
LineWhat it does · ทำอะไร · 做什么
(-?[0-9.]+)The ? means the minus may be there or not.เครื่องหมาย ? หมายถึงมีลบก็ได้ ไม่มีก็ได้那个 ? 表示负号可以有,也可以没有。
if ($1 > 0)awk compares it as a number, because it looks like one.awk เทียบมันแบบตัวเลข เพราะมันหน้าตาเหมือนตัวเลขawk 按数字来比,因为它看起来就是个数字。
-$1 "%"A minus in front flips the sign. Two values side by side join up.ลบข้างหน้าจะกลับเครื่องหมาย ค่าสองค่าที่อยู่ติดกันจะต่อกัน前面加个负号就翻转符号。两个值挨着写就接在一起。

4Do not log the same day twice · อย่าบันทึกวันเดิมสองครั้ง · 同一天不要记两次

🇬🇧 English

log_price.sh adds a line every time you run it. Run it twice and today appears twice.

Check the log first. Only add the line if today is not in it.

🇹🇭 ไทย

log_price.sh เพิ่มบรรทัดทุกครั้งที่รัน ถ้ารันสองครั้ง วันนี้จะโผล่สองรอบ

ตรวจบันทึกก่อน เพิ่มบรรทัดเฉพาะเมื่อยังไม่มีวันนี้อยู่ในนั้น

🇨🇳 中文

log_price.sh 每跑一次就加一行。跑两次,今天就出现两遍。

先查一下记录。只有今天还不在里面时才加。

Show the answerดูเฉลย看答案
# log_once.sh — the same log, but safe to run all day.

TODAY=$(date +%F)
LOG=price_log.csv

# touch makes an empty file if there is none, so grep has something to read.
touch "$LOG"

# -q means say nothing, just answer with the exit number. The ! flips it,
# so the body runs only when today was NOT found.
if ! grep -q "^$TODAY," "$LOG"; then
  curl -sS -f "https://api.bitkub.com/api/v3/market/ticker?sym=BTC_THB" \
    | sed -E 's/.*"last":"([0-9.]+)".*/\1/' \
    | awk -v day="$TODAY" '{printf "%s,%.2f\n", day, $1}' \
    >> "$LOG"
  echo "added $TODAY"
else
  echo "$TODAY is already there"
fi
LineWhat it does · ทำอะไร · 做什么
grep -q "^$TODAY,"^ means the start of the line. The comma stops a half match.^ คือต้นบรรทัด จุลภาคกันการตรงแค่ครึ่งเดียว^ 是行首。那个逗号防止只匹配到一半。
if ! grep -q ...; thenThe ! flips the answer. Run the body when it was not found.เครื่องหมาย ! กลับคำตอบ ให้ทำส่วนในเมื่อหาไม่เจอ! 把答案反过来。没找到时才跑里面。
touch "$LOG"Makes an empty file on the first run. Then grep has something to read.สร้างไฟล์ว่างในการรันครั้งแรกสุด grep จะได้ไม่บ่น第一次跑时造一个空文件,grep 就不会抱怨。

5The best day your log ever saw · วันที่ดีที่สุดที่บันทึกของคุณเคยเห็น · 你的记录见过的最好一天

🇬🇧 English

Read the whole log. Print the date with the highest price.

Keep the best one as you go. Print it at the END.

🇹🇭 ไทย

อ่านบันทึกทั้งไฟล์ พิมพ์วันที่ที่ราคาสูงสุด

เก็บอันที่ดีที่สุดไว้เรื่อย ๆ แล้วพิมพ์ตอน END

🇨🇳 中文

把整份记录读完。打出价格最高的那个日期。

一边走一边留住最好的那个。到 END 再打出来。

Show the answerดูเฉลย看答案
# Three days of made-up log, so the answer is easy to check by eye.
printf '2026-09-25,2805205.52\n2026-09-26,2819755.67\n2026-09-27,2799000.00\n' > log.csv

# The test is in front, so this only runs on a line that beats the record.
# best starts empty, which counts as zero, so line one always wins.
awk -F, '$2 > best { best = $2; day = $1 } END { printf "%s %.2f\n", day, best }' log.csv

🖥️ WHAT IT PRINTED

2026-09-26 2819755.67
LineWhat it does · ทำอะไร · 做什么
$2 > bestA test, not an action. Only a better line gets in.เป็นเงื่อนไข ไม่ใช่การกระทำ มีแค่บรรทัดที่ดีกว่าที่ผ่านเข้าไป这是条件,不是动作。只有更好的行能进去。
{ best = $2; day = $1 }Remembers two things at once. The date and the price stay together.จำสองอย่างพร้อมกัน วันที่กับราคาอยู่ด้วยกัน一次记住两样。日期和价格一起留着。
END { printf ... }Only now, after every line has been read.ตอนนี้เท่านั้น หลังจากอ่านทุกบรรทัดจบแล้ว到现在才打,等每一行都读完之后。

6Cheapest and dearest, without awk · ถูกสุดและแพงสุด โดยไม่ใช้ awk · 最便宜和最贵,不用 awk

🇬🇧 English

Same question as challenge 5. This time use sort.

sort needs three facts. Which separator, which column, and that they are numbers.

🇹🇭 ไทย

คำถามเดียวกับข้อ 5 ครั้งนี้ใช้ sort

sort ต้องรู้ตัวคั่น รู้ว่าคอลัมน์ไหน และรู้ว่ามันเป็นตัวเลข

🇨🇳 中文

和第 5 题同一个问题。这次用 sort。

sort 需要知道分隔符、第几列,以及它是个数字。

Show the answerดูเฉลย看答案
# -t, sets the separator. -k2 picks column two. -n compares as numbers.
# Without -n, sort puts 100 before 9, because it reads them as words.
echo "cheapest:"
sort -t, -k2 -n log.csv | head -1

echo "dearest:"
sort -t, -k2 -n log.csv | tail -1

🖥️ WHAT IT PRINTED

cheapest:
2026-09-27,2799000.00
dearest:
2026-09-26,2819755.67
WITHOUT -n, SORT PUTS 100 BEFORE 9 By default sort compares words, one letter at a time. In that world 1 comes before 9, so 100 comes before 9. Any column of numbers needs -n. This one is easy to miss. A short list often looks right by luck. ปกติ sort เทียบแบบคำ ทีละตัวอักษร ในโลกแบบนั้น 1 มาก่อน 9 ดังนั้น 100 จึงมาก่อน 9 คอลัมน์ตัวเลขใด ๆ ต้องใช้ -n ข้อนี้พลาดกันง่าย เพราะลิสต์สั้น ๆ มักดูถูกต้องด้วยความโชคดี 默认情况下 sort 按词比,一个字母一个字母地比。在那个世界里 1 排在 9 前面,所以 100 排在 9 前面。任何一列数字都需要 -n。这个很容易漏掉,因为短列表常常碰巧看起来是对的。

7Save it and see it, at the same time · เก็บไว้และเห็นด้วย ในเวลาเดียวกัน · 存起来,同时也看得到

🇬🇧 English

> has one annoying habit. The answer goes to the file, so you cannot see it.

There is a tool whose whole job is to do both. Find it.

🇹🇭 ไทย

> มีนิสัยน่ารำคาญอยู่ข้อหนึ่ง คำตอบไปอยู่ในไฟล์ คุณจึงมองไม่เห็นมัน

มีเครื่องมือหนึ่งที่มีหน้าที่ทำทั้งสองอย่าง ไปหามันมา

🇨🇳 中文

> 有个烦人的毛病。答案进了文件,你就看不见它了。

有个工具的全部工作就是两件一起做。把它找出来。

Show the answerดูเฉลย看答案
# tee is named after a T pipe. What comes in goes two ways at once:
# into the file, and on down the pipe to your screen.
curl -sS -f "https://api.bitkub.com/api/v3/market/ticker?sym=BTC_THB" \
  | sed -E 's/.*"last":"([0-9.]+)".*/\1/' \
  | tee latest.txt

cat latest.txt

🖥️ WHAT IT PRINTED · once from tee, once from cat

2818749.09
2818749.09
LineWhat it does · ทำอะไร · 做什么
| tee latest.txtWrites the file and prints it. Named after a T shaped pipe.เขียนไฟล์และพิมพ์ออกจอ ชื่อมาจากท่อรูปตัว T写文件,同时打出来。名字来自 T 形水管。
tee -a latest.txt-a appends instead. It is the >> of tee.-a คือต่อท้ายแทน มันคือ >> ของ tee-a 改成追加。它就是 tee 的 >>。

🇬🇧 English

You started with echo and one file. You finished with a live price log.

None of these tools is clever. Each does one small thing. The pipe is what makes them strong.

That is the whole idea of the terminal. Small tools, joined in a line.

🇹🇭 ไทย

คุณเริ่มจาก echo กับไฟล์หนึ่งไฟล์ และจบด้วยบันทึกราคาจริง

เครื่องมือพวกนี้ไม่มีอันไหนฉลาด แต่ละอันทำเรื่องเล็ก ๆ เรื่องเดียว ท่อคือสิ่งที่ทำให้มันแข็งแรง

นั่นคือแนวคิดทั้งหมดของเทอร์มินัล เครื่องมือเล็ก ๆ ต่อกันเป็นแถว

🇨🇳 中文

你从 echo 和一个文件开始,最后做出一份实时的价格记录。

这些工具没有一个聪明。每个只做一件小事。是管子让它们变强的。

这就是终端的全部想法。小工具,排成一行接起来。

You wantคุณอยากได้你想要Look upไปหาคำว่า去查
Find a word in many filesหาคำในหลายไฟล์在很多文件里找一个词grep -r
Pick out column threeดึงเอาคอลัมน์ที่สาม取出第三列cut -d, -f3
Drop repeated linesตัดบรรทัดที่ซ้ำกันออก去掉重复的行sort | uniq
Find files by nameหาไฟล์จากชื่อ按名字找文件find . -name
Read JSON properlyอ่าน JSON อย่างถูกวิธี正经地读 JSONbrew install jq
Run it every day by itselfให้มันรันเองทุกวัน让它每天自己跑crontab -e
FOR REAL JSON WORK, INSTALL jq LATER This page cut JSON with sed on purpose. Every Mac can do it, with nothing installed. But sed does not understand JSON. It only sees text. Change the order of the fields and your rule breaks. When JSON becomes your daily job, install jq. Until then, what you learned here works everywhere. หน้านี้ตัด JSON ด้วย sed อย่างตั้งใจ แมคทุกเครื่องทำได้ โดยไม่ต้องติดตั้งอะไร แต่ sed ไม่เข้าใจ JSON มันเห็นแค่ข้อความ ถ้าลำดับของฟิลด์เปลี่ยน กฎของคุณจะพัง เมื่อ JSON กลายเป็นงานประจำวันของคุณ ให้ติดตั้ง jq ก่อนถึงวันนั้น สิ่งที่คุณเรียนที่นี่ใช้ได้ทุกที่ 这一页故意用 sed 来切 JSON。每台 Mac 都做得到,什么都不用装。但 sed 不懂 JSON,它只看见文字。字段顺序一变,你的规则就坏了。等 JSON 成了你每天的活,就装 jq。在那之前,你在这里学到的到处都能用。