[英]When processing string with Bash, how to treat comma differently depending on whether it's surrounded by some specific characters?
我想將 MySQL 腳本轉換為 JSON 文件,並被要求使用 Bash 文件。 通過編寫一個簡單的 shell 腳本:
#!/bin/bash
# I know this script just output each entry with its value, because I haven' t gone any further
for filename in $dir/home/*.sql
do
cat $filename | while read line
do
names=${line%values*}
names=${names#*(}
names=${names%)*}
values=${line#*values(}
values=${values%)*}
while [[ $names != $currentname ]]
do
currentname=${names%%,*}
currentvalue=${values%%,*}
echo $currentname
echo $currentvalue
names=${names#*,}
values=${values#*,}
done
done
done
我已經基本可以滿足要求了。 然而,還有一個問題。 一些字符串條目的字符中有逗號。
這會導致一個錯誤,即我的腳本將這些逗號視為分隔值的逗號,因此帶有逗號的字符串將被視為兩個不同的字符串。
使用 C++ 之類的編程語言來解決這個問題很容易,但我被要求只使用 bash shell 腳本來解決這個問題,盡管我不熟悉它。 所以現在我一直毫無頭緒。 也許正則表達式可以治愈? 或者如果有其他方法也請幫忙。
僅供參考,這是問題的一個示例:
輸入:
values(100, 'A100', 'A,100');
預期 output:
100
'A100'
'A,100'
實際電流output:
100
'A100'
'A
100'
這樣的事情可能會有所幫助:
data="values(100, 'A100', 'A,100');"
json=${data//values(}
json=${json//);}
json=${json//, /$'\n'}
echo "$json"
預期 output:
通常在 shell 中,您會將其與正則表達式匹配:
echo "values(100, 'A100', 'A,100');" | sed 's/values(//; s/\(, \|);\)/\n/g'
但這根本不能解決問題。
最好也是唯一的解決方案是為真正的mysql 語言編寫一個真正的解析器,以正確地'handle' '' ' ' 'all\tcorner\'cases'
。 逐個字符讀取輸入的字符,存儲 state(例如,如果您在引號內),處理'\''
和其他\n
等序列以滿足提取字段的需要。 您可能會對mysql 內部詞法分析器(它很大!)以及 lex 和 yacc 程序感興趣。
使用http://shellcheck.net檢查您的腳本。 閱讀https://mywiki.wooledge.org/BashFAQ/001 。 引用變量擴展。 不要被無用貓獎提名。
並被要求使用 Bash 。
Bash 是 shell - 它的主要作用是運行和連接其他程序。 Bash 是 shell,不是一門成熟的編程語言,在其中編寫編程內容將非常困難,或者最終只能使用外部程序,因為這就是它的用途。 用其他語言編寫解析器 - 使用 bash 運行它。 If you're comfortable in C++, write it in C++ inside a bash script, then compile and execute it inside a bash script.
一個常見的安排是為此使用正則表達式,是的; 例如,這是解析 CSV 文件的要求。 但是您可以像嘗試一樣逐段解析行。
但是,即使您找到了一種按您想要的方式解析輸入的方法,您也會遇到許多引用錯誤,這些錯誤會阻止您的代碼工作。 (當然,擺脫cat 的無用用法? )
while read -r line; do
case $line in
*values\(*\)\; );;
*) continue;;
esac
line=${line#values\(}
line=${line%\)\;}
while [ "$line" ]; do
case $line in
\'*)
line=${line#\'}
tail=${line#*\'}
value=\'${line%"$tail"}
line=${tail#,}
line=${line# };;
*) value=${line%%,*}
line=${line#*,}
line=${line# };;
esac
echo "$value"
done
done <"$filename"
這可能不是真正通往 go 的方法,如果您真的想嘗試在 Bash 中解決這個問題,這只是一個提示。 如果我想涵蓋所有基礎,我會在 Python 中編寫一個簡單的解析器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.