从文本文件生成具有特定结构的新文件


0

在Linux上我有文件 orig-file.txt。此文件现在包含4个字段,但它们可能更少或更多(此文件由其他应用程序生成)。

什么是翻译的最佳选择 orig-file.txt 到像这样的文件 output-file.txt 文件(可能是shell脚本或awk等)

原稿-file.txt的

CREATE_TIMESTAMP              TELEPHONE_NUMBER             ID TYPE
-------------------           -------------------- ---------- -----------------
24-09-2009 16:17:45           33633333333                  20 other_mmm_phone
24-09-2009 17:45:07           33644444444                  20 other_mmm_phone
07-10-2009 10:45:49           12312312312                  20 legacyphone
07-10-2009 11:46:38           59320000043                  20 other_mmm_phone

输出file.txt的

CREATE_TIMESTAMP -> 24-09-2009 16:17:45
TELEPHONE_NUMBER -> 33633333333
ID               -> 20
TYPE             -> other_mmm_phone



---



CREATE_TIMESTAMP -> 24-09-2009 16:17:45
TELEPHONE_NUMBER -> 33633333333
ID               -> 20
TYPE             -> other_mmm_phone

---

来自awk lang的例子 - (但它不起作用 - :(

# awk 'NR>2 {
 > printf "\
 > %-16s -> %s\n\
 > %-16s -> %s\n\
 > %-16s -> %s\n\
 > %-16s -> %s\
 > \n\n\n---\n\n\n",\
 >         "CREATE_TIMESTAMP", $1" "$2,\
 >         "TELEPHONE_NUMBER", $3,\
 >         "ID", $4,\
 >         "TYPE", $5}\
 > '   orig-file.txt
awk: newline in string near line 2
awk: syntax error near line 3
awk: illegal statement near line 3
awk: newline in string near line 7

您的原始文件和输出文件都不是CSV。
slhck

好的,请参阅我的更新(我删除CSV字)你不是CSV而是具有特定结构的其他文件
yael

嗯。我很抱歉挑选这些单词,但这是一个愚蠢的文件结构来操纵。如果它是一个CSV文件,它会非常简单,但这里几乎不可能解析。你不能以其他格式获取数据吗?
slhck

谁是愚蠢的文件 - orig-file.txt?还是输出文件.txt? - 你的建议是什么?请给我另一个例子,我可以从orig-file.txt文件中获得最佳格式?
yael

1
output-file.txt 在我眼里是一种糟糕的格式。即使手动阅读也不太清楚 orig-file.txt 恕我直言。
Daniel Andersson

Answers:


0

这是一些普通的ksh:

{
  read t1 t2 t3 t4
  maxlen=$(printf "%s\n" ${#t1} ${#t2} ${#t3} ${#t4} | sort -n | tail -1)
  fmt=$(printf "%%-%ds -> %%s" $maxlen)
  read line
  while read date time tel id type; do
    printf "$fmt\n" $t1 "$date $time" $t2 $tel $t3 $id $t4 $type
    print "\n\n\n---\n\n"
  done
} < orig-file.txt

更新 灵活的字段数:

我替换datetime字段中的空格以使事情更容易解析

sed '3,$s/ /@@/' orig-file.txt | 
{
    read line
    set -A headings $line
    max=0
    for head in "${headings[@]}"; do (( max < ${#head} )) && max=${#head}; done
    fmt=$(printf "%%-%ds -> %%s" $max)

    read line

    while read line; do
        set -A fields $line
        i=0
        while (( i < ${#headings[@]} )); do
            printf "$fmt\n" ${headings[$i]} ${fields[$i]} | sed 's/@@/ /'
            (( i=i+1 ))
        done
        print "\n\n\n---\n\n"
    done
}

好的非常酷 - 但如果我的文件将包含5或6个字段而不是4,我会怎么做 - 我们可以创建更灵活的语法吗?支持任何数量的字段??? (例如,我有定义字段数的参数 - NUM_OF_FIELDS)
yael

示例[[$ NUM_OF_FIELDS -eq 4]]&amp;&amp;读t1 t2 t3 t4或[[$ NUM_OF_FIELDS -eq 5]]&amp;&amp;读t1 t2 t3 t4 t5 ......等
yael

@yael,更新为使用数组。
glenn jackman

0

在这种情况下,这可以完成工作。如果添加更多字段,则需要进行简单修改。

awk 'NR>2{
    printf "\
%-16s -> %s\n\
%-16s -> %s\n\
%-16s -> %s\n\
%-16s -> %s\
\n\n\n---\n\n\n",\
        "CREATE_TIMESTAMP", $1" "$2,\
        "TELEPHONE_NUMBER", $3,\
        "ID", $4,\
        "TYPE", $5}\
' orig-file.txt > output-file.txt

“CREATE_TIMESTAMP”需要两者 $1$2 因为日期本身是空格分隔的。


可以修改它以从标题中读取字段名称,但是日期是空格分隔的问题。如果允许其他字段包含空格,则总是需要手动修改以补偿,例如 $1" "$2 案件。


但是如何在我的ksh脚本中构建这个awk? ,如果我们有五个或更多的字段,我需要添加的第二个?
yael

1
@yael:就像你对任何其他工具一样。管道它,或让它从临时文件中读取,依此类推。这不在您当前的问题范围内。
Daniel Andersson

好但是看到我的更新awk无法在ksh shell上运行?
yael

@yael:我在某些行的末尾使用反斜杠,以便能够继续在下面的行上书写,以便清晰地呈现。只需删除所有结束行的反斜杠,然后删除所有换行符,将整个命令写在一行上。这应该普遍适用。
Daniel Andersson
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.