簡體   English   中英

使用 Bash 處理字符串時,如何根據逗號是否被某些特定字符包圍而區別對待?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM