Bash子串从位置不打印

时间:2013-05-07 14:19:45

标签: linux string bash scripting

我使用以下格式#{string:start:length}逐行从wget的.listing文件中提取文件名。

该文件的格式是我认为我们都熟悉的:

04-30-13  01:41AM              7033614 some_archive.zip
04-29-13  08:13PM       <DIR>          DIRECTORY NAME 1
04-29-13  05:41PM       <DIR>          DIRECTORY NAME 2

所有文件名都以pos:40开头,因此将:start设置为39,没有:length应该(并且确实)返回每行的文件名:

#!/bin/bash
cat .listing | while read line; do
    file="${line:40}"
    echo $file
done

正确回归:

some_archive.zip
DIRECTORY NAME 1
DIRECTORY NAME 2

但是,如果我再获得更多创意,那就会破坏:

#!/bin/bash
cat .listing | while read line; do
    file="${line:40}"
    dir=$(echo $line | egrep -o '<DIR>' | head -n1)
    if [ $dir ]; then
        echo "the file $file is a $dir"
    fi
done

返回:

$ ./test.sh
 is a <DIR>ECTORY NAME 1
 is a <DIR>ECTORY NAME 2

是什么给出的?我丢失了“文件”,其余的测试看起来像是从pos:0打印在“文件DIRECTORY NAME 1”之上。

这很奇怪,它的含义是什么?

2 个答案:

答案 0 :(得分:1)

答案是,随着我的进步,我越来越多地学习linux,它是非打印控制字符。

仅为打印字符添加管道egrep解决了问题:

#!/bin/bash
cat .listing | while read line; do
    file=$(echo ${line:39} | egrep -o '[[:print:]]+' | head -n1)
    dir=$(echo $line | egrep -o '<DIR>' | head -n1)
    if [ $dir ]; then
        echo "the file $file is a $dir"
    fi
done

正确回归:

$ ./test.sh
the file DIRECTORY NAME 1 is a <DIR>
the file DIRECTORY NAME 2 is a <DIR>

希望有一种更好的方法可视化这些控制字符,但上面所做的基本上是取字符串段,拉出第一个可打印字符串,并将其分配给变量。

我假设在行的末尾有一个控制字符,它将光标返回到行的开头。导致其余的echo被打印出来,覆盖以前的字符。'

答案 1 :(得分:1)

您可以使用脚本第一行的\r命令从整个文件中删除tr个控制字符:

#!/bin/bash
cat .listing | tr -d '\015' | while read line; do
    file="${line:39}"
    dir=$(echo $line | egrep -o '<DIR>' | head -n1)
    if [ $dir ]; then
        echo "the file $file is a $dir"
    fi
done