Bash:如何从文件开头删除 0x0A 字符

Bash:如何从文件开头删除 0x0A 字符

在行之前的某个地方count=~echo "$conflict" | wc -l~(~ 代替反引号),0x0A添加了十六进制字符。因此,当文件$DA$DB相同时(意味着脚本应返回一个空集),0x0A将添加。因此,下一个命令中的行数不是零,而是 1。它被添加到循环每次迭代的输出末尾。对于返回其他内容的循环来说,这不是什么大问题,但对于应该返回空集的循环来说,这很烦人(因此,不应创建新文件)。我尝试在行的开头和结尾插入tr -d '\r'和,但没有帮助。tr -d '\n'conflict=~cat "$DA" "$DB"

我怎样才能简单地删除仅包含此字符(或实际上除 之外的任何不可打印字符\n)的任何行?

非常感谢您的帮助。

# Files "DA" and "DB" are titled as such:
# 10M_$i_$j_$m_OtherNonRelevantChars or 10M_$i_$k_$n_OtherNonRelevantChars
# Field one is an integer; fields 2 and 3 are alphanumeric (checksum hashes)

IFS=$'\n'

for i in {1..7}
    do for j in {P,B,R}
        do for k in {P,B,R}
            do for m in {3,9}
                do for n in {3,9}
                    do 
                        DA=`ls "10M_${i}_${j}_${m}"*`
                        DB=`ls "10M_${i}_${k}_${n}"*`
                        dos2unix "$DA" "$DB"
                
                        conflict=`cat "$DA" "$DB" | \
                            awk  -v OFS=',' -F',' '{print $1,substr($2,0,8),substr($3,0,8)}' | \
                            sort -t',' -k1,1n | uniq -u | \
                            awk -v i=$i -v j=$j -v k=$k -v m=$m -v n=$n -v OFS=',' -F',' '{print i,j,m,k,n,$1}' | \
                            uniq -d`

                        # The unwanted character appears somewhere before here
                        count=`echo "$conflict" | wc -l`
                        if [[ "$count" -gt 0 ]]
                            then 
                                echo $conflict  >> "C_${i}_${j}_${m}_${k}_${n}.txt" # output of conflicting hashes for given matching unique first field ID
                        fi
                        echo "$i $j $m $k $n"
                    done
                done
            done
        done
    done

答案1

$count总是大于零,因为echo添加换行符。以下每个命令都会打印1

conflict=""; echo "$conflict" | wc -l
             echo ""          | wc -l
             echo             | wc -l

回显包含换行符的变量的内容只能增加计数。

事情是这样的:

  • 命令替换()conflict=删除所有尾随换行符

  • 因此我们可以考虑几种情况:

    1. 如果换行符后跟非换行符,则变量将包含至少一个换行符。
    2. 如果第一个线不是空的并且所有(零个或多个)以下行都为空,则变量将非空,但它将包含零个换行符。
    3. 如果只有一个不完整的线那么变量将非空,但它将包含零个换行符。
    4. 如果所有行都是空的,那么变量也将为空;因此它将包含零个换行符。
    5. 如果输出为空,则变量将为空;因此它将包含零个换行符。
  • 如前所述,echo只添加一个换行符。

  • wc -l计算换行符。当我们说它计算行数时,我们指的是正式定义的线。 一个不完整的线从这些术语上来说,并不是一条线。

因此,在echo至少有一个换行符之后,并且[[ "$count" -gt 0 ]]始终为真。更糟糕的是,使用printfecho -n来避免添加额外的换行符(将其与考虑在内-gt 1)并不是一个解决方案,因为“恰好一行”和“空输出”(以及少数其他情况)在变量中生成相同数量的换行符:零。

在你的情况下大概测试一下是否$conflict不为空就足够了:

[ -n "$conflict" ]

一般来说,你可能想要继续使用换行符。不过看来你的第二个awk不能生成空行。


注意如果你count直接计算,没有中间conflict变量

count="$(cat … | … | wc -l)"

那么就没有问题了。我注意到你$conflict稍后使用(你不想引用它吗?),因此这种方法实际上不是一个选择(除非您决定独立获取countconflict,但这不是最优的,并且一般来说,当输入数据在其间发生变化时可能会导致不一致的结果)。


让我们回到不完整的行。您正在使用dos2unix。在 DOS/Windows 世界中,文本文件可能以不完整的行结尾(例如POSIX 术语)。如果发生这种情况,dos2unix则不完整的行之后仍将不完整。运行时至少有两个潜在问题cat "$DA" "$DB" | …

  1. 如果第一个文件以不完整的行结束,那么它将与第二个文件的开头连接起来,中间没有任何换行符。
  2. 如果第二个文件以不完整的行结尾,则输出cat将以此行结束,管道中稍后的工具可能会“行为不当”。文本处理工具期望文本线。一般来说,当遇到不完整的线时,此类工具可能会:
    • 忽略不完整的线,就好像它不存在一样;
    • 或者接受它并将它(想象一个类似的过滤器grep)作为不完整的行传递到它的输出;
    • 或者接受它,修复(添加换行符)并将其作为完整的行传递给其输出;
    • 或抛出错误(例子)。

因此请注意您的输入文件。

相关内容