从文件中划分标题并将其转换为包含序列号的列,包括Unix中的文件号

时间:2013-06-10 14:44:18

标签: unix

我的输入文件是allresponses_11.txt,其中包含带标题的数据:

ID NAME LOC PH
T1 BA KA 99
T2 GT HS 98

我想要输出如下。

seq_num file_num hname
1 11 ID
2 11 NAME
3 11 LOC
4 11 PH

请帮我在unix中获得所需的输出。文件名需要动态传递。

在你的帮助下,我制作了如下脚本,但它为每个单词提供了标题输出。我的标题按标签分隔,标题内有空格。

#!/bin/ksh

export INFAHOME=/informat/PowerCenter/9.1.0/server/infa_shared
export SRCDIR=${INFAHOME}/SrcFiles/CSI/INCOMING
export filename=${SRCDIR}/AllResponses_11003_6_7_20132_17_33AM1.txt
export filenum=$(echo $filename | tr -dc 0-9 |cut -c 1-5)

echo seq_num file_num hname

cnt=1
for h in $(head -1 "$filename")
do
    echo $cnt $filenum $h
    cnt=$((cnt+1))
done

我的输出应该是

SEQ_NUM  FILE_NUM  HNAME
1  11003  TOTAL COUNT
2  11003  FINAL DAY
3  11003  LADT COUNT

我的源文件分隔符是制表符,但我的标题列名称有空格。

3 个答案:

答案 0 :(得分:1)

您的文件约会惯例:

export filename=${SRCDIR}/AllResponses_11003_6_7_20132_17_33AM1.txt

太可怕了。如果你使用如下符号:

,这将使你的生活更轻松
filename=${SRCDIR}/AllResponses_11003_2013_06_07_02_17_33_1.txt

或更紧凑的表示法,例如:

filename=${SRCDIR}/AllResponses_11003_20130607_021733_1.txt

然而,这与现有讨论相关。请注意,您不需要在太阳下导出每个变量 - 在此脚本中,不需要导出任何导出的变量。

您的路径名称:

export INFAHOME=/informat/PowerCenter/9.1.0/server/infa_shared

包含三个数字,您在代码中未考虑这些数字来提取文件的序列号。


我可能会根据您的需要使用awk来处理数据,使用如下脚本的变体:

#!/bin/bash

INFAHOME=/informat/PowerCenter/9.1.0/server/infa_shared
SRCDIR=${INFAHOME}/SrcFiles/CSI/INCOMING
filename=${SRCDIR}/AllResponses_11003_6_7_20132_17_33AM1.txt
filenum=$(basename $filename | sed 's/^[^_]*_\([0-9][0-9]*\)_.*/\1/')

echo seq_num file_num hname

sed 1q "$filename" |    
awk -F $'\t' -v filenum=$filenum '{ for (i = 1; i <= NF; i++) print i, filenum, $i;}'

我已将'shell'切换为bash以允许使用$'\t'将标签嵌入awk命令行。你可以很好地使用ksh代替单引号,制表符和另一个单引号,但很难在SO Markdown中区分空格与制表符。

filenum的分配使用basename来获取文件名。 bash afficionado会写${filename##*/}代替;这可能也适用于ksh。随后的sed命令会在一系列非下划线后捕获由下划线包围的一串数字。

awk命令使用选项卡作为输入字段分隔符,从而处理以制表符分隔的包含空格的标题元素。

给定一个数据文件,例如:

TOTAL COUNT     FINAL DAY       LADT COUNT
100     Friday  102

(其中多个空白的每个序列是数据文件中的一个选项卡)和filenum=11003,输出为:

seq_num file_num hname
1 11003 TOTAL COUNT
2 11003 FINAL DAY
3 11003 LADT COUNT

如果您也想要以制表符分隔的输出列,请将OFS="\t";添加到awk脚本中:

awk -F$'\t' -v filenum=11003 '{ OFS="\t"; for (i = 1; i <= NF; i++) print i, filenum, $i;}'
1       11003   TOTAL COUNT
2       11003   FINAL DAY
3       11003   LADT COUNT

sed 1q命令不是绝对必要的。你可以awk忽略除第一行输入之外的所有内容:

awk -F $'\t' -v filenum=$filenum 'NR==1 { for (i = 1; i <= NF; i++)
                                              print i, filenum, $i;
                                        }'

如果您愿意,可以awk打印标题;如果需要以制表符分隔,这可能有价值。

答案 1 :(得分:0)

虽然你的问题有点缺乏细节,但我认为这至少可以达到你想要的目的:

filename=allresponses_11.txt
filenum=$(echo ${filename} | tr -dc 0-9)
echo "seq_num file_num hname"
for h in $(head -1 ${filename})
do
  echo "${filenum} ${h}"
done | cat -n

答案 2 :(得分:0)

您可以使用awk来获取答案

awk -F $'\ t'-v filenum = $ filenum'{for(i = 1; i <= NF; i ++)打印i,filenum,$ i;}'