区切りファイルの形式を再指定し、行を複数行に分割します。

区切りファイルの形式を再指定し、行を複数行に分割します。

次の入力があります。

FIELD1   FIELD2   FIELD3   FIELD4
aaaa   bbbb   cccc   dddd
eeee   ffff
           gggg   hhhh
iiii   jjjj   kk   llll
              kk

空白で区切られたレコードのリストでなければなりませんが、何かが間違って記録されました。

正しい行は最初の行と似ています。他の行は、中間(2行目)に改行があるか、フィールドの内側(3行目の3番目のフィールド)に改行があるため、フィールドに書き込まれます。

私が望むのは、次のように注文された出力を取得することです。

FIELD1   FIELD2   FIELD3   FIELD4
aaaa   aaaa   aaaa   aaaa
bbbb   bbbb   bbbb   bbbb
cccc   cccc   cccc   cccc

awkROW2のような行を変更できる場合は、ROW3を変更することも似ているようですが、 "\ n \ s * "bbbb"を "bbbb"に置き換えるなどのいくつかのツールを使用したり、一度に複数の行を表示する方法を理解していません。sed. ROW2 を修正します。

編集する:

私が持っている実際のデータの一部は次のとおりです。

G00PFMA1     transition_readonly 2   cifs     0.0.0.0/0             any
G00PFMA7     transition_export_policy_1 1
                                     nfs      10.58.91.134          sys
G00PFMA7     transition_export_policy_1 2
                                     nfs      bmczone.tsy.fm.       sys
                                              hypovereinsbank.de
G00PFMA7     transition_export_policy_1 3
                                     nfs      inf01mz2              sys

フィールドはスペースで区切られます。 ROW1は各行の外観ですが、ROW2とROW4にはFIELD3とFIELD4の間に改行があり、ROW3にはFIELD5の内部に改行があるようです。これはExcelファイルからコピーして貼り付けた結果であるため、フィールド内に改行がある可能性があるためです。

編集2:

このテキストの場合、正しい出力は次のようになります。

G00PFMA1     transition_readonly 2   cifs     0.0.0.0/0             any
G00PFMA7     transition_export_policy_1 1 nfs      10.58.91.134          sys
G00PFMA7     transition_export_policy_1 2 nfs      bmczone.tsy.fm.hypovereinsbank.de       sys
G00PFMA7     transition_export_policy_1 3 nfs      inf01mz2              sys

答え1

まず、分割線を修正して分割列を無視してみましょう。

$ grep -v "^\s*[^ ]*$" file | grep -o "[^ ]*" | paste - - - - - -
G00PFMA1    transition_readonly 2   cifs    0.0.0.0/0   any
G00PFMA7    transition_export_policy_1  1   nfs 10.58.91.134    sys
G00PFMA7    transition_export_policy_1  2   nfs bmczone.tsy.fm. sys
G00PFMA7    transition_export_policy_1  3   nfs inf01mz2    sys

説明する:

  • 単一要素のみを含む行をフィルタリングします。

    grep -v "^\s*[^ ]*$" file
    
  • すべてのアイテムを別々の行に配置

    grep -o "[^ ]*"
    
  • 1行あたり6列に戻ります。

    paste - - - - - -
    

あなたのニーズには十分かもしれませんが、不十分で移植性の低い完全な解決策を得ました。分割される唯一の列は5列で、常に6つの列があるとします。

{
print_items(){
    # print if there are 6 elements
    if [ $# = 6 ]; then
      echo "$@"
    # print if there are 7 elements, but merge element 5 and 7 before printing
    elif [ $# = 7 ]; then
      set -- "${@:1:4}" "${5}${7}" "${@:6:1}"
      echo "$@"
    fi
}
items=()
while IFS= read -r line; do
    # Get start position of first item
    start_position=$(grep -o "^ *" <<< "$line" | wc -c)
    # if start_position is 0 then create new array items with elements in the line
    if [ $start_position = 0 ]; then
        # when new line starts, print previous line
        print_items "${items[@]}"
        items=( $line )
    # if start_position is not 0, add the elements in the line to the existing items array
    else
        items+=( $line )
    fi
    # Print items
done < file
# print last line
print_items "${items[@]}"
} | column -t

出力:

G00PFMA1  transition_readonly         2  cifs  0.0.0.0/0                          any
G00PFMA7  transition_export_policy_1  1  nfs   10.58.91.134                       sys
G00PFMA7  transition_export_policy_1  2  nfs   bmczone.tsy.fm.hypovereinsbank.de  sys
G00PFMA7  transition_export_policy_1  3  nfs   inf01mz2                           sys

関連情報