【问题标题】:How can I split a file in order to obtain parameters with shell?如何拆分文件以使用 shell 获取参数?
【发布时间】:2020-01-17 20:19:30
【问题描述】:

我的文件有问题,我需要把它的每一行分开并将它们作为参数发送到另一个 shell。该文件包含以下几行

20191224900|1
20191230901|1
20200107905|1
2020020891|1
2020010984|1

比如第一行要这样分割

19
12 
24 
900

第二行要这样分割

19 
12
30
901

对于每个循环,必须将这些数字发送到另一个 shell

例子:

another_shell $19 $12 $30 $901

但是当我运行测试时,我得到的唯一结果是文件按列划分,我需要对每一行单独应用拆分并发送参数

while read line; 
do 
    echo "year"
    awk '{print substr($1,3,2)}'
    echo "month"
    awk '{print substr($1,5,2)}' 
    echo "day"
    awk '{print substr($1,7,2)}' 
    echo "store"
    sed 's/|1//' REPROCESO_VTA_20200107.txt | awk '{print substr($1,9,3)}'
done < REPROCESO_VTA_20200107.txt

【问题讨论】:

  • another_shell $19 $12 $30 $901 肯定是不对的。这是试图传递当前 shell 的位置参数,包括 901st,这没有多大意义,尤其是在上下文中。你的意思是another_shell 19 12 30 901
  • @JohnBollinger 没有花括号,它相当于another_shell ${1}9 ${1}2 ${3}0 ${9}01,我也认为这不是意图......
  • 你是对的,@BenjaminW.,我的错。而且我认为这不太可能是 OP 真正想要的。
  • 你构建 while 循环的方式是错误的。 while read line 将读取 1 行输入。 awk 然后将消耗其余的输入。然后sed 将读取整个文件。然后read会尝试读取失败,循环只进行一次迭代。

标签: linux shell file split parameters


【解决方案1】:

在您的代码中...

while read line; 
do 
    echo "year"
    awk '{print substr($1,3,2)}'
    echo "month"
    awk '{print substr($1,5,2)}' 
    echo "day"
    awk '{print substr($1,7,2)}' 
    echo "store"
    sed 's/|1//' REPROCESO_VTA_20200107.txt | awk '{print substr($1,9,3)}'
done < REPROCESO_VTA_20200107.txt

...您告诉sed 在每次循环迭代时处理整个输入文件。这与在每次迭代中通过read 命令从同一文件中读取一行的shell 完全不同。由于您的意图似乎只是从每一行中删除任何尾随的|1,这也很浪费。将结果通过管道传输到单独的awk 进程中更加浪费,因为

  • 你可以用sed 完成你用awk 做的事情,在这种情况下跳过你实际正在sed 做的事情(或反之亦然 em>);和
  • 您对这两者所做的一切都可以轻松地直接在 shell 中完成,而无需启动单独的进程。

此外,您似乎试图用awk 做的所有其他事情可以在 shell 代码中完成,而不是为这些小任务启动整个单独的进程。

考虑一下:

while read line; do

  # strip the shortest trailing substring matching the glob |*
  line=${line%|*}

  # split the string based on fixed field widths for all but the last field,
  # using the results as arguments to an execution of some_program.
  # The quoting may be overkill.  It is unnecessary when all lines of the
  # input comply with the specified format.
  some_program "${line:2:2}" "${line:4:2}" "${line:6:2}" "${line:8}"

done < REPROCESO_VTA_20200107.txt

【讨论】:

  • 我在应用此解决方案时收到此消息 --> 指定的替换对于此命令无效,此环境中的 shell 已过时。我要继续工作。非常感谢
  • 这似乎不太可能与上面的具体建议有关,@CristopherVergara,但在不知道您使用的是什么版本的 shell 的情况下,我不能再说什么。
【解决方案2】:

一个非常脆弱的想法:只需添加一些空格。假设您的 another_shell 实际上不是 shell 而只是一些命令,您可以执行以下操作:

$ cat a.sh
#!/bin/sh

cat << EOF |
20191224900|1
20191230901|1
20200107905|1
2020020891|1
2020010984|1
EOF
sed -E 's/(..)(..)(..)(..)([^|]*)/\1 \2 \3 \4 \5 /' |
while read _ one two thre four _; do
        echo "$one" "$two" "$thre" "$four"
done
$ ./a.sh
19 12 24 900
19 12 30 901
20 01 07 905
20 02 08 91
20 01 09 84

将上面的echo替换为another_shell就完成了。

【讨论】:

    猜你喜欢
    • 2011-06-12
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    • 2013-08-05
    • 2018-09-27
    • 2015-05-23
    • 2020-12-08
    • 2017-06-22
    相关资源
    最近更新 更多