要素にスペースがある bash 配列

要素にスペースがある bash 配列

テキストログファイルがあります

$ cat aaa
673                  20160405 root "/path_to/gis/20160401/20160301_placement_map_org.dbf" ""
673                  20160405 root "/path_to/gis/20160401/20160310_20160401ent_map_org.dbf" ""
790890               20170201 jle  "/path_to/gis/20160401/Pina (Asc) 20160401 Rapid Report.kmz" ""
5883710              20160406 dho  "/path_to/gis/20160401/20160401_Pina_Asc_Rapid_Report_Minesouth.pdf" ""
673                  20160405 dho  "/path_to/gis/20160401/20160310_20160401 placement map org.dbf" ""

これで、私のスクリプトはファイルのフルパスのみを出力します。

#!/bin/bash

function nodatechk() {
    arr=("$@")
    for ((i=3;i<${#arr[@]};i+=5));
    do
      echo "${i}" "${arr[i]}"
    done
}

r=( $(grep gis aaa) ) 

nodatechk "${r[@]}"

3行目(および5行目)に二重引用符が含まれていても、要素にスペースがあるため、出力が壊れていました。

この問題をどのように解決できますか? (ところで、awkまたはcutを使用して列を印刷できることを知っていますが、この場合はgrepを使用したいと思います。)ありがとう。

ベストアンサー1

問題の根本原因は次のとおりです。

 r=( $(grep gis aaa) )

試してみると、次の内容がすぐに表示されます。

 printf '<%s>\n' $(grep gis aaa)

「$IFS」内の文字(デフォルトでは空白、タブ、改行)に基づいて分割されます。

そしてファイルの値をワイルドカードに公開します。これにより、いくつかの*?および[…](いくつかはパスワードのファイルのリストといくつかのシェルオプションに依存します)が変換されます。

1つの(推奨されていない)解決策はIFS分割文字に変更することです。そして分割を無効にするワイルドカード:

 IFS=$'\n'; set -f; r=( $(grep gis aaa) )

しかし、より簡単な解決策は、シェルによってすでに提供されている機能を使用することです。

readarray -t r <(grep gis aaa) 

これは改行文字に分割されます(パス名に改行文字がないと仮定)。

次に、行を空白とワイルドカードに公開する可能性がある各部分を取得するために、行を再分割しないように行の前後の部分を削除します。

"/各行の先頭から(二重引用符とスラッシュ)までのすべての項目と"(二重引用符とスペース)から終わりまでのすべての項目を削除すると、きれいなパス名を取得できます。

 #!/bin/bash

 function nodatechk() {
    for l do
        l="/${l#*\"/}"                # Remove leading text up to `"/`
        l=${l%\" *}                   # Remove trailing text from `" `
        printf '%s\n' "$l"
    done
 }

 readarray -t r < <(grep gis aaa)

 nodatechk "${r[@]}"

おすすめ記事