AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / computer / 问题 / 1425158
Accepted
Brian
Brian
Asked: 2019-04-14 13:40:32 +0800 CST2019-04-14 13:40:32 +0800 CST 2019-04-14 13:40:32 +0800 CST

bash 脚本:回显输出乱码且顺序错误

  • 772

我遇到了以意外顺序回显输出的 bash 脚本问题。脚本如下。问题在于第 30-32 行的输出。


1 IFS=$'\n'
2 i=1
3 bluered=""
4 blueyellow=""
5 redyellow=""
6 all=""
7 while [ $i -le `cat sorted.csv | wc -l` ]
8       do
9           for j in {0..2}
10               do
11                     # cat sorted.csv | head -$i | tail -1 | awk -F',' '{print $1}'
12                     declare "`cat sorted.csv | head -$i | tail -1 | awk -F',' '{print $1}'`=`cat sorted.csv | head -$i | tail -1 | awk -F','   '{print $5}'`"
13                     i=$((i+1))
14               done
15
16           if [[ ${blue} == ${red} ]]; then bluered=1; else bluered=0; fi
17           if [[ ${blue} == ${yellow} ]]; then blueyellow=1; else blueyellow=0; fi
18           if [[ ${red} == ${yellow} ]]; then redyellow=1; else redyellow=0; fi
19           if [[ ${blue} == ${red} ]] && [[ ${red} == ${yellow} ]]; then all=1; else all=0; fi
20
21           echo "`cat sorted.csv | head -$((i-3)) | tail -1`"
22           echo ",$all,$bluered,$blueyellow,$redyellow"
23           echo "`cat sorted.csv | head -$((i-2)) | tail -1`"
24           echo ",$all,$bluered,$blueyellow,$redyellow"
25           echo "`cat sorted.csv | head -$((i-1)) | tail -1`"
26           echo ",""$all"",""$bluered"",""$blueyellow"",""$redyellow"
27
28
29
30           echo  "`cat sorted.csv | head -$((i-3)) | tail -1`,$all,$bluered,$blueyellow,$redyellow"
31           echo  "`cat sorted.csv | head -$((i-2)) | tail -1`"",$all,$bluered,$blueyellow,$redyellow"
32           echo  "`cat sorted.csv | head -$((i-1)) | tail -1`"",""$all"",""$bluered"",""$blueyellow"",""$redyellow"
33       done

第 30-32 行的双引号格式略有不同,因为我尝试了不同的方法来使其正常工作。第 21-26 行无非是将第 30-32 行分解为两部分(即第 21-22 行与第 30 行相同)。

基于输入文件“sorted.csv”,第 30-32 行(对于输入文件的前 3 行)的正确输出应该是:

blue,1,WCC131035882,0,e89d89d7ca7c502ca8d3b2e0d7c4980dba346a63d57a437d8f1428065fb83e9f,0,0,0,1
red,1,Z292V5DB,0,68a4917c878f1b26e370264097f476840aa995dc6b8d6d2e552a78a6bdd77c68,0,0,0,2
yellow,1,Z292V94K,0,68a4917c878f1b26e370264097f476840aa995dc6b8d6d2e552a78a6bdd77c68,0,0,0,1

但实际输出是:

,0,0,0,1CC131035882,0,e89d89d7ca7c502ca8d3b2e0d7c4980dba346a63d57a437d8f1428065fb83e9f #(line 30 output)
,0,0,0,192V5DB,0,68a4917c878f1b26e370264097f476840aa995dc6b8d6d2e552a78a6bdd77c68 #(line 31 output)
,0,0,0,1,Z292V94K,0,68a4917c878f1b26e370264097f476840aa995dc6b8d6d2e552a78a6bdd77c68 #(line 32 output)

第 21 - 26 行返回以下输出:

blue,1,WCC131035882,0,e89d89d7ca7c502ca8d3b2e0d7c4980dba346a63d57a437d8f1428065fb83e9f #(line 21 output)
,0,0,0,1 #(line 22 output)   
red,1,Z292V5DB,0,68a4917c878f1b26e370264097f476840aa995dc6b8d6d2e552a78a6bdd77c68 #(line 23output)
,0,0,0,1 #(line 24 output)
yellow,1,Z292V94K,0,68a4917c878f1b26e370264097f476840aa995dc6b8d6d2e552a78a6bdd77c68 #(line 25)
,0,0,0,1 #(line 26 output)

简而言之,我想使用 3 个单行命令(如第 30-32 行(但语法正确))连接第 21-22、23-24 和 25-26 行的输出。注意,第 21-26 行仅包含在该脚本用于演示第 30 行(31 或 32)的两部分在分成两行时是否正常工作。目前,第 30 行有效地连接了第 22 行和第 21 行的输出,而不是第 21 行和第 22 行的输出。但是,在进行这种反向连接时,它还截断了第 21 行输出的前 8 个字符(注意,输出第 22 行正好是 8 个字符)。

我如何正确编写第 30-32 行以便它们创建所需的输出?

提前感谢你的帮助。

linux bash script
  • 2 2 个回答
  • 2009 Views

2 个回答

  • Voted
  1. Best Answer
    Kamil Maciorowski
    2019-04-14T17:30:28+08:002019-04-14T17:30:28+08:00

    比简洁的“使用dos2unix”更具洞察力。

    显然sorted.csv使用 CR+LF 行尾,而它应该只使用 LF。

    当您`something`在输出的末尾使用换行符 (LF) 时,something会去除,但不会去除回车符 (CR)。在你的情况下text+CR+LF成为text+CR. 如果它是 的唯一输入echo,该工具会像往常一样添加一个换行符,并且最后会有 CR+LF。在打印到控制台时,此 CR 没有任何变化。

    但是如果echo "`foo`bar"CR 返回的字符foo停留在结果字符串的中间,那么后面的任何内容都会从控制台的左边缘打印出来,覆盖前面的部分。

    dos2unix sorted.csv正如您已经指出的那样,解决方案是使用。


    但还有更多:

    • 无用的使用cat
    • $(stuff)和 和有什么不一样`stuff`?
    • 为什么printf比echo?
    • 许多出现的""(例如在第 32 行中)什么都不做。他们是关闭+打开,而不是打开+关闭。他们只会混淆代码。我知道它们是“实验性的”,我明确地说它们没有任何改变。

    也许_

    • echo $(stuff)or有什么问题echo `stuff`?

      我承认这个反对意见在这里是有问题的。"`foo`bar"从输出中去除任何尾随的 LFfoo并将其与连接起来很有用bar;在你的情况下这很重要。然后使用 like 语法echo "`foo`"来演示行为的相关差异,您明确说明了这一点。


    dos2unix当然没有回答这个问题,这是[强调我的]:

    我如何正确编写第 30-32 行以便它们创建所需的输出?

    正确编写的第 32 行至少会使用printf, no cat。$( … )反引号和过多的引号可能会保留,尽管代码在合理引用的情况下更具可读性。您也可以考虑将格式与数据分开,这很容易printf:

    printf '%s,%s,%s,%s,%s\n' "$( <sorted.csv head -$((i-1)) | tail -1 )" "$all" "$bluered" "$blueyellow" "$redyellow"
    

    另外其他地方也有不好的解决办法:

    • while [ $i -le `cat sorted.csv | wc -l` ](除了cat和反引号)。无需获取每次迭代的行数。wc -l sorted.csv应该在循环之前运行一次,它的结果存储在一个变量中(除非你期望行数在执行过程中发生变化,但我认为你不会;如果数字不变,脚本的逻辑更有意义).

    • 你一次又一次地重新阅读文件。行数越多,您重新打开、从头开始阅读并每次选择一行的次数就越多。应该重新设计流程,以便逐行解析文件,可能没有 prior wc -l,可能以类似管道的方式(即只打开一次,只读取一次而不跳回)。由于您使用declare内置的,while IFS= read -r … ; done <sorted.csv可能是必须的(也许是 preliminary awk,例如<sorted.csv awk … | while IFS= read -r …)。你可以read对三个不同的变量进行三次操作,然后执行操作;然后阅读接下来的三行。read本身效率低下,但比多次重新打开文件更优雅。请注意,文件中每增加一行,脚本的效率就会降低;如果文件大到足以read表现出低效率,您的方法可能会执行得更糟。

      如果你愿意,这整个改变将不会是微不足道的。

    • 文件名不应该在这么多地方硬编码。只读取一次文件自然会减少这个问题。即便如此,开始使用input_file="sorted.csv"并"$input_file"在任何需要的地方使用也是好的。如果您决定将文件路径作为命令行参数传递,那么只需键入input_file="$1".

    • 为什么没有shebang?

    考虑到大局,更正确的第 30-32 行应该是这个片段:

    #!/bin/bash
    input_file="sorted.csv
    …
    while IFS= read -r pre_previous_line && IFS= read -r previous_line && IFS= read -r current_line; do
       …
       # useful bashism instead of    echo "$previous_line" | some_command
       some_command <<< "$previous_line"
       …
       # printf will reuse the format if there are more arguments than the format needs
       # so this one line will be enough for your three
       # (split for readability, it's still one line for the shell)
       printf '%s,%s,%s,%s,%s\n' \
          "$pre_previous_line" "$all" "$bluered" "$blueyellow" "$redyellow" \
          "$previous_line"     "$all" "$bluered" "$blueyellow" "$redyellow" \
          "$current_line"      "$all" "$bluered" "$blueyellow" "$redyellow"
       …
    done <"$input_file"
    

    可能仅awk作为过滤器工作就可以做到这一点;该文件将通过管道传输给它。您也可以将信息存储在awk变量中,以便以后使用。条件也可用。像这个未经充分测试的例子:

    #!/usr/bin/awk -f
    BEGIN { FS="," }
    {
    if ($1 == "blue") blue=$5
    if ($1 == "red") red=$5
    if ($1 == "yellow") yellow=$5
    if (NR%3 == 1) prepre=$0
    if (NR%3 == 2) pre=$0
    if (NR%3 == 0)
       {
       bluered=($blue == $red)
       blueyellow=($blue == $yellow)
       redyellow=($red == $yellow)
       all= bluered * blueyellow
       suffix=","all","bluered","blueyellow","redyellow
       print prepre suffix
       print pre    suffix
       print $0     suffix
       }
    }
    

    (注意:awk我用 is in fact 测试过mawk)。保存它,使其可执行,通过管道将sorted.csv其传递给它(例如<sorted.csv ./the_script)。

    • 2
  2. Brian
    2019-04-14T14:51:01+08:002019-04-14T14:51:01+08:00

    关于回车在文件中的评论是正确的。在运行输入文件 thought dox2unix 后,脚本按预期运行。谢谢,戈登。

    • 0

相关问题

  • Notify-发送窗口下出现的通知

  • 以 root 身份运行 docker 容器

  • 如何在域和 Linux 活动目录中启用指纹传感器

  • 如何在CentOS 7 中将Ctrl+C 永久更改为Ctrl+K?

  • 如何从 WSL 打开 office 文件

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    Windows 照片查看器因为内存不足而无法运行?

    • 5 个回答
  • Marko Smith

    支持结束后如何激活 WindowsXP?

    • 6 个回答
  • Marko Smith

    远程桌面间歇性冻结

    • 7 个回答
  • Marko Smith

    Windows 10 服务称为 AarSvc_70f961。它是什么,我该如何禁用它?

    • 2 个回答
  • Marko Smith

    子网掩码 /32 是什么意思?

    • 6 个回答
  • Marko Smith

    鼠标指针在 Windows 中按下的箭头键上移动?

    • 1 个回答
  • Marko Smith

    VirtualBox 无法以 VERR_NEM_VM_CREATE_FAILED 启动

    • 8 个回答
  • Marko Smith

    应用程序不会出现在 MacBook 的摄像头和麦克风隐私设置中

    • 5 个回答
  • Marko Smith

    ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获取本地颁发者证书 (_ssl.c:1056)

    • 4 个回答
  • Marko Smith

    我如何知道 Windows 安装在哪个驱动器上?

    • 6 个回答
  • Martin Hope
    Albin 支持结束后如何激活 WindowsXP? 2019-11-18 03:50:17 +0800 CST
  • Martin Hope
    fixer1234 “HTTPS Everywhere”仍然相关吗? 2019-10-27 18:06:25 +0800 CST
  • Martin Hope
    Kagaratsch Windows 10 删除大量小文件的速度非常慢。有什么办法可以加快速度吗? 2019-09-23 06:05:43 +0800 CST
  • Martin Hope
    andre_ss6 远程桌面间歇性冻结 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney 为什么在 URL 后面加一个点会删除登录信息? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension 鼠标指针在 Windows 中按下的箭头键上移动? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    Inter Sys Ctrl+C 和 Ctrl+V 是如何工作的? 2019-05-15 02:51:21 +0800 CST
  • Martin Hope
    jonsca 我所有的 Firefox 附加组件突然被禁用了,我该如何重新启用它们? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK 是否可以使用文本创建二维码? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 更改 git init 默认分支名称 2019-04-01 06:16:56 +0800 CST

热门标签

windows-10 linux windows microsoft-excel networking ubuntu worksheet-function bash command-line hard-drive

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve