1

カンマ区切りの列を持つテーブルがあり、指定した列のカンマ区切りの値を新しい行に区切りたい。たとえば、与えられたテーブルは

Name    Start   Name2

A   1,2 X,a

B   5   Y,b

C   6,7,8   Z,c

そして、以下の表を取得するには、列2のコンマ区切り値を区切る必要があります

Name    Start   Name2

A   1   X,a

A   2   X,a

B   5   Y,b

C   6   Z,c

C   7   Z,c

C   8   Z,c

ワークフローパイプを作成できるように、シェルスクリプトを使用した解決策があるかどうか疑問に思っています。

注:元のテーブルには3つ以上の列が含まれている場合があります。

4

2 に答える 2

0

入力と出力の形式が変わらないと仮定すると、次のようになります。

awk 'BEGIN{FS="[ ,]"} {print $1, $2, $NF; print $1, $3, $NF}' input_file

入力:

input_file:

A 1,2 X    
B 5,6 Y

出力:

A 1 X
A 2 X
B 5 Y
B 6 Y

説明:

  • awkawk:行 (レコード) およびフィールドを操作するためのツールであるinvoke
  • '...': 一重引用符で囲まれた内容はawk、指示として提供されます
  • 'BEGIN{FS="[ ,]"}: 行を読み取る前に、区切り文字としてスペースとコンマの両方を使用するように awk に指示します。FS はフィールド セパレーターの略です。
  • {print $1, $2, $NF; print $1, $3, $NF}: 読み取られた入力行ごとに、1 番目、2 番目、および最後のフィールドを 1 行に出力し、次に 1 番目、3 番目、および最後のフィールドを次の行に出力します。NF は Number of Fields の略で$NF、最後のフィールドです。
  • input_file: 入力ファイルの名前を awk に引数として指定します。

更新された入力形式への対応:

awk 'BEGIN{FS="[ ,]"} {print $1, $2, $4","$5; print $1, $3, $4","$5}' input_file
于 2012-12-04T16:43:22.917 に答える
0

ランナーが元の質問を修正した後、別のアプローチは次のようになります。

#!/bin/sh

# Usage $0 <file> <column>
#

FILE="${1}"

COL="${2}"

# tokens separated by linebreaks
IFS="
"

for LINE in `cat ${FILE}`; do
    # get number of columns
    COLS="`echo ${LINE} | awk '{print NF}'`"

    # get actual field by COL, this contains the keys to be splitted into individual lines
    # replace comma with newline to "reuse" newline field separator in IFS
    KEYS="`echo ${LINE} | cut -d' ' -f${COL}-${COL} | tr ',' '\n'`"

    COLB=$(( ${COL} - 1 ))
    COLA=$(( ${COL} + 1 ))

    # get text from columns before and after actual field
    if [ ${COLB} -gt 0 ]; then
            BEFORE="`echo ${LINE} | cut -d' ' -f1-${COLB}` "
    else
            BEFORE=""
    fi

    AFTER=" `echo ${LINE} | cut -d' ' -f${COLA}-`"

    # echo "-A: $COLA ($AFTER) | B: $COLB ($BEFORE)-"

    # iterate keys and re-build original line
    for KEY in ${KEYS}; do
            echo "${BEFORE}${KEY}${AFTER}"
    done
done

このシェル ファイルを使用すると、必要なことを実行できます。これにより、列 2 が複数の行に分割されます。

./script.sh input.txt 2

パイプを使用して標準入力を介して入力を渡したい場合 (たとえば、複数の列を一度に分割する場合)、 6. 行を次のように変更できます。

if [ "${1}" == "-" ]; then
    FILE="/dev/stdin"
else 
    FILE="${1}"
fi

そして、次のように実行します。

./script.sh input.txt 1 | ./script.sh - 2 | ./script.sh - 3

カットは、フィールドセパレーターに非常に敏感であることに注意してください。そのため、行がスペース文字で始まる場合、列 1 は "" (空) になります。フィールドがスペースとタブの混合で区切られている場合、このスクリプトには他の問題もあります。この場合、(上で説明したように) 入力リソースをフィルタリングする (フィールドが 1 つの空白文字だけで区切られるようにする) 必要があります。これが不可能な場合、または各列のデータにも空白文字が含まれている場合、スクリプトはより複雑になる可能性があります。

于 2012-12-27T21:33:15.287 に答える