我有一个以下格式的文本文件,我想使用shell脚本

时间:2017-09-02 15:22:15

标签: bash shell sed

~1
ACCOUNT1
34765367
001
5637463648374
1
32476743
85468456875
003
~1
~2
ACCOUNT2
23587458745647
1
002343
2347938457
~2

.... SO ON

我想将其打印成以下格式的另一个文件:

ACCOUNT134765367001563746364837413247674385468456875003
ACCOUNT22358745874564710023432347938457

我在下面写了这样的东西,直到~9完美地工作,但是对于~10,它也将~10记录添加到~1记录,在~1记录的末尾。我想我需要更新我的正则表达式模式...请帮助

max_input=2
path1=/home
line_number_m=1
while [ ${line_number_m} -le ${max_input} ]
do
o_p=""
sed -n "/^${line_number_m},/^~{line_number_m}/p" ${path1}/temp_op.txt | sed 
"s/^${line_number_m}//" > ${path1}/tmp.txt
while read val
do
if [ -z ${val} ]
then
continue
else
o_p=`echo ${o_p}``echo ${val}`
fi
done< ${path1}/tmp.txt
echo ${o_p} >>${path1}/tmp_output.txt
line_number_m=`expr ${line_number_m} + 1`
done
rm ${path1}/tmp.txt
tail -n +2 ${path1}/tmp_output.txt > ${path1}/output.txt
rm ${path1}/tmp_output.txt
exit 0

~1和~1内的记录可以是任何随机数或字符,甚至是如下所示的空格:      〜1      001      13324324343      共同      6      487364754557465      --2space      5874654657      --- 3空间      48567846574      4568746574657      --5spaces ---      〜1

我想要我的输出如下: 00113324324343COMMON6487364754557465--5874654657 --- 485678465744568746574657 -----

5 个答案:

答案 0 :(得分:1)

试试这个,希望可以帮助你作为一个起点:

#!/bin/bash

while IFS='' read -r line || [[ -n "$line" ]]; do
    if [[ $line == ACCOUNT* ]]
    then
        printf '\n%s' "$line"
    elif [[ $line != ~* ]]
    then
        printf '%s' "$line"
    fi
done < "$1"

将其保存到文件中并尝试:

./script.sh data.txt

同时查看以下答案:https://stackoverflow.com/a/2172367/1135424

# The == comparison operator behaves differently within a double-brackets
# test than within single brackets.

[[ $a == z* ]]   # True if $a starts with an "z" (wildcard matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).

答案 1 :(得分:1)

在gawk或awk而不是sed对我来说更容易。 Awk已经处理了记录,所以它特别擅长这样的任务。您只需告诉它如何识别记录分隔符,以及您想要对字段执行的操作。在这种情况下,在偶数编号的记录中,我们删除所有空格,然后打印。

gawk -v RS='~[0-9]+' 'NR%2==0 {gsub(/[[:space:]]/,"");print}'

这依赖的gawk功能是复杂(正则表达式)RS变量。在BSD或macOS中,您可能需要类似以下内容,在连接记录中的所有字段之前清空第一个字段:

awk -v RS='~' 'NR%2==0 {$1="";gsub(/[[:space:]]/,"");print}'

如果你真的想在sed中这样做,我想你可以用以下内容来捏造它:

sed -Ene $'H;${x;s/[[:space:]]//g;s/~[0-9]+A/\\\nA/g;s/~[0-9]*//g;p;}'

这会将整个文件放入保留空间,与awk脚本相同的空格减少,然后在清除字段分隔符的过程中重新添加换行符。

答案 2 :(得分:0)

管道:

$ sed '/^~/d' data | tr -d '\n' | sed -re 's/(.)A/\1\nA/g' -e 's/$/\n/'
ACCOUNT134765367001563746364837413247674385468456875003
ACCOUNT22358745874564710023432347938457
  • 第一个sed删除所有以~开头的行。
  • tr将所有内容连接成一行输出。
  • 最后sed使用字符AACCOUNT)作为分隔符再次将输入分成单独的行,并在末尾添加换行符。

最后sed要求GNU sed能够使用\n插入换行符。

答案 3 :(得分:0)

$ sed '/^~/d' data | awk -v RS='A' -v OFS='' '$1 && $1=RS $1'
ACCOUNT134765367001563746364837413247674385468456875003
ACCOUNT22358745874564710023432347938457

这是我对这个问题的第二个解决方案。

首先sed删除所有以~开头的行。

awk然后将剩余数据作为由字符A分隔的记录读取,并在输出字段之前连接字段(没有分隔符)。

这不依赖于GNU实用程序。

答案 4 :(得分:0)

这可能适合你(GNU sed):

sed -rn '/^~/{:a;N;/^(~[0-9]+)\n(.*)\n\1$/!ba;s//\2/g;s/\s//g;p}' file

收集连续分隔符之间的行,即以~n开头的行,其中n是整数。取下分隔符,去除空白区域并打印。