如何使用bash有选择地删除换行符?

时间:2014-05-30 01:29:48

标签: bash file-io sed newline

我有一个带有stacktraces的server.log文件,其编写方式如下:

timestamp texttexttexttext \n
  at texttexttexttext\n
  at texttexttexttext\n
  at texttexttexttext\n
caused by texttexttexttext\n
  at texttexttexttext\n
  at texttexttexttext\n
  at texttexttexttext\n
  at texttexttexttext\n

以及这样写的警告/信息,所有信息都在一行中:

timestamp texttexttexttexttext \n

我想解析日志文件,以便唯一的换行符是时间戳之前的那一行;这样堆栈跟踪都是一行,我可以稍后循环遍历它,只需要回显一次以显示整个堆栈跟踪。基本上我希望大型堆栈跟踪看起来像这样:

timestamp texttexttexttext
  at texttexttexttext
  at texttexttexttext
  at texttexttexttext
caused by texttexttexttext
  at texttexttexttext
  at texttexttexttext
  at texttexttexttext
  at texttexttexttext\n

我试图遍历这些行,如果它以时间戳开头,我在它之前添加换行符,如果它没有以时间戳开头,我使用sed用空格替换换行符。下面是循环:注释显示我试图将它全部放在一个字符串中以便稍后循环它,但我也尝试将它全部放在一个文件中以便稍后再进行。

for x in "$(cat tempFile.txt)" 
do
    if [[ ! $x =~ [0-2][0-9](:+).* ]]
    then
        #STRINGBUILDER+=`printf "%s" $x | sed 's/"$NL"/" "/'`
        printf "%s" $x | sed 's/$'\n'/" "/' > parsed.txt
    else
        #STRINGBUILDER+=`printf "\n%s" $x`
        printf "\n%s" $x > parsed.txt
    fi
done

但是,无论我以后如何遍历文件,新行似乎仍然存在。我如何摆脱它们?

3 个答案:

答案 0 :(得分:1)

您遇到的具体问题是循环中只有一个参数:整个文件内容。这是因为"$(cat tempFile.txt)"被引用,因此它被完全分配给变量$x

这里有一些(未经测试的)代码可以使用,但我也不得不质疑正则表达式...它没有锚定,所以尾随.*是无意义...

if read line; then
  while read next_line; do
    if [[ $next_line =~ [0-2][0-9]: ]]; then
        echo "$line"
    else
        echo -n "$line "
    fi
    line=$next_line
  done
  echo "$line"
fi < tempFile.txt > parsed.txt

答案 1 :(得分:0)

如果您希望从文件构造一个字符串,并echo使用所需的行格式构建字符串,您可以这样做:

str=""
while IFS= read -r line; do
    if [[ $line =~ ^[0-2][0-9]:+ ]]; then
        string+="$line"
    else
        string+="${line/\\n/\ }"
    fi
done < file
echo -en "$string\n"

如果您知道时间戳位于该行的开头,则.*是不必要的。您可以使用^添加正则表达式。如果您希望访问BASH_REMATCH内置数组变量,则只需将括号括在Bash中。

答案 2 :(得分:0)

Awk声明应该有效。

awk 'BEGIN {ORS=""};!/[1-2][1-9]/ {print} /[1-2][1-9]/{printf("\n%s",$0)}' tempFile.txt > parsed.txt;

工作原理:

BEGIN {ORS=""}

将输出记录分隔符设置为空,因此不会打印换行符。

!/[1-2][1-9]/ {print}

如果它不是时间戳行(你可以添加更多正则表达式。我不知道格式)然后打印行。

/[1-2][1-9]/{printf("\n%s",$0)}'

如果是时间戳行,则打印换行符然后行