0

我的输入文件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

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

4

3 回答 3

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;}'

我已经“切换外壳”bash以允许使用$'\t'将选项卡嵌入awk命令行。您可以很好地使用ksh它并将其替换为单引号、制表符和另一个单引号,但在 SO Markdown 中很难区分空格与制表符。

filenum用于basename获取文件名的分配。一个bash爱好者会改写${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打印标题;如果它们需要制表符分隔,那可能会有好处。

于 2013-06-11T11:37:50.463 回答
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
于 2013-06-10T15:29:53.740 回答
0

你可以使用 awk 来得到你的答案

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

于 2020-08-06T07:08:22.767 回答