shell脚本执行中的字符串连接错误

时间:2016-11-02 01:54:37

标签: java shell awk sed grep

这是一个令我困惑的连线问题好几天。我希望通过解析shell中的java代码文件来获取一个类的完整类名。我们可以从中获取包名:

包com.android.mail.ui;

从代码文件路径获取类名,使用shell命令' basename'。 下面是我的shell脚本:

#!/bin/bash
get_package_name(){
   java_file=$1
    if [ ! -f $file_path ]; then 
        echo "Sorry,the java file is not exist:$1,please check"
        exit 1
    fi      
    class_base_name=`basename "$java_file" .java`
    echo "class_base_name:$class_base_name"
    package_name=`grep $java_file -e "^package" | awk -F " " '{print $2}' | tr ';' ' ' | sed 's/ //g'`
    echo "package_name get result:$?"
    echo "package_name:$package_name"

方法1,直接使用变量concat

    classpath_name=$package_name.$class_base_name
    echo "method 1 classpath_name:$classpath_name"

方法2,使用sed replace间接获取concat

    classpath_name2=`echo "aa.bb" | sed "s/aa/$package_name/" | sed "s/bb/$class_base_name/"`
    echo "method 2 classpath_name2:$classpath_name2"

}

  

问题是:对于某些代码文件,结果是可以的,例如:   " class_base_name:MailTransport package_name get result:0   package_name:com.android.email.mail.transport方法1   classpath_name:com.android.email.mail.transport.MailTransport方法2   classpath_name2:com.android.email.mail.transport.MailTransport"

     

对于其他人,它的输出是:" class_base_name:EmailApplication   package_name get result:0 package_name:com.android.email   .EmailApplicationh_name:com.android.email   .EmailApplicationh_name2:com.android.email"

     

结果是完全混乱和错误。我怀疑它与代码有关   内容,这对结果真的有意义吗?

1 个答案:

答案 0 :(得分:1)

这是因为您的某些文件使用Windows样式的CRLF(\r\n)行终止符。

以下是一个可行的示例,一个普通的Unix样式LF(\n)终止文件:

$ file WorkingFile.java
WorkingFile.java: ASCII text

$ cat -v WorkingFile.java
package foo.bar.baz;

$ get_package_name WorkingFile.java
class_base_name:WorkingFile
package_name get result:0
package_name:foo.bar.baz
method 1 classpath_name:foo.bar.baz.WorkingFile

这是一个失败的示例,使用CRLF行终止符:

$ file FailingFile.java
FailingFile.java: ASCII text, with CRLF line terminators

$ cat -v FailingFile.java
package foo.bar.baz;^M        <--- note hidden control char revealed by -v

$ get_package_name FailingFile.java
class_base_name:FailingFile
package_name get result:0
package_name:foo.bar.baz
.FailingFilesspath_name:foo.bar.baz

要修复它,您可以使用tr -d '\r'删除额外的回车。我从传统的反引号切换到现代$()以避免反斜杠的问题:

package_name=$(grep $java_file -e "^package" | awk -F " " '{print $2}' | tr ';' ' ' | sed 's/ //g' | tr -d '\r')

有关详细信息,请参阅this relevant post