【问题标题】:AWK passing loop variablesAWK 传递循环变量
【发布时间】:2022-01-28 05:30:09
【问题描述】:

所以我有这个包含时间戳的文件。

cat file
2022/01/27-00:47:05;2022/01/27-00:47:05;
2022/01/27-00:47:06;2022/01/27-00:47:06;
2022/01/27-00:48:59;2022/01/27-00:48:59;
2022/01/27-01:38:06;2022/01/27-01:38:06;
2022/01/27-01:45:17;2022/01/27-01:45:17;
2022/01/27-01:47:46;2022/01/27-01:47:47;
<bunch of lines>
2022/01/27-15:00:01;2022/01/27-15:00:01;
2022/01/27-15:00:05;2022/01/27-15:00:05;
2022/01/27-15:00:06;2022/01/27-15:00:06;

我试图创建一个 for 循环来隔离所有第一个字段为 2022/01/27-hour:.

的行

到目前为止,这是我想出的,但它不起作用:

for var in {00..23}
do
awk -F ';' -v var="$var" '$1 ~2022/01/27-var"' file > $var.txt
done

我没有得到任何输出。

试图完成的是获取 24 个文件,其内容是每小时的时间戳。

00.txt:第一个字段与 2022-01-27-00

匹配的所有行

01.txt:第一个字段匹配 2022-01-27-01

的所有行

…/…

23.txt:第一个字段匹配 2022-01-27-23

的所有行

我显然遗漏了一些东西,但我不知道是什么,因为其他东西似乎工作得很好。

for kk in {00..23}
do
echo | awk -v kk="$kk" '{print kk}'
done
00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23

我一定是以错误的方式传递变量。

任何帮助将不胜感激。

【问题讨论】:

  • 是的,完全正确:我没有得到任何输出。根据循环替换,预期输出应该是第一个字段包含 2022/01/27-$var: 2022/01/27-00, 2022/01/27-01 的所有行。
  • 您的输入文件中是否保证在目标日期的每个小时内都有条目?如果不是,是否应该创建该小时的空输出文件?

标签: variables awk


【解决方案1】:

您可以显式使用match 而不是~。例如:

awk 'match($1,"2022/01/27-" var )' var=00 FS=\; input

【讨论】:

    【解决方案2】:

    假设:

    • 所有行都以日期时间戳开头,例如YYYY/MM/DD-HH:
    • 日期时间戳可能涵盖多天,但输出文件仍仅基于 HH(即,每个 HH.txt 文件可能包含不同日期的数据)

    一个GNU awk 想法消除了对bash 循环的需要:

    awk -F'[-:]' '{print $0 > $2".txt"}' file
    

    注意事项:

    • -F'[-:] - 定义两个输入字段分隔符(-:
    • 使用字段 #2 作为输出文件名的前缀
    • 我们谈论的是最多 24 个输出文件,因此不存在最大化打开文件描述符数量的问题

    对于给定的样本输入(没有&lt;bunch of lines&gt; 行),这会生成:

    $ for fname in {00..23}.txt; do [[ -f "${fname}" ]] && echo "########### $fname" && cat $fname; done
    ########### 00.txt
    2022/01/27-00:47:05;2022/01/27-00:47:05;
    2022/01/27-00:47:06;2022/01/27-00:47:06;
    2022/01/27-00:48:59;2022/01/27-00:48:59;
    ########### 01.txt
    2022/01/27-01:38:06;2022/01/27-01:38:06;
    2022/01/27-01:45:17;2022/01/27-01:45:17;
    2022/01/27-01:47:46;2022/01/27-01:47:47;
    ########### 15.txt
    2022/01/27-15:00:01;2022/01/27-15:00:01;
    2022/01/27-15:00:05;2022/01/27-15:00:05;
    2022/01/27-15:00:06;2022/01/27-15:00:06;
    

    【讨论】:

    • print $0 &gt; $2".txt" 依赖于未定义的行为(输入/输出重定向右侧的表达式周围没有括号),因此会在某些 awk 中产生语法错误。在超过我在 15-20 个输出文件范围内看到的阈值后,它还会在某些 awks 中导致“打开的文件过多”错误。它会在 GNU awk 中做你想做的事,所以你可以这么说。
    • 它还假设在给定小时内总是有条目,因为如果没有,那么它不会为那个小时创建输出文件,这与 OPs shell 循环版本不同。
    【解决方案3】:

    使用您显示的示例/尝试,请尝试关注awk 程序。该程序根据第一个字段对您的 Input_file 进行排序,然后将其输出作为输入传递给 awk 程序。在awk 程序中,将-: 作为每行的字段分隔符。然后它检查行的第一个字段是否为2022/01/27 AND 第二个字段是 2 位然后将整行打印到第二个字段(这是小时值)。它还负责关闭后端的输出文件以避免“打开的文件过多”错误。

    sort -s -t';' -k1 Input_file | 
    awk -F'[-:]' '
    $1=="2022/01/27" && $2~/^[0-9]{2}$/ {
      outFile = $2 ".txt"
      if ( prev != outFile ) {
        close(prev)
        prev = outFile
      }
      print > outFile
    }
    '
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多