计算每一行中文件的特定字符,并在特定位置删除该字符

时间:2018-08-04 00:07:57

标签: bash

如果您能在Solaris环境中的此脚本中为我提供帮助,我将不胜感激。

场景:

我有2个文件:

1)/tmp/TRANSACTIONS_DAILY_20180730.txt:

201807300000000004 
201807300000000005 
201807300000000006 
201807300000000007 
201807300000000008

2)/opt/TRANSACTIONS_DAILY_20180730.txt

20180730|201807300000000005||50001521111200|0106276-4|5SIJ00|WIRE||EUR|EUR|20180730|20180730|||||||0000000000030 0.00|00000000000300.00|Credit||||||||||SIJ|||500015|506|||||||||||||||||||||||||FI3158410220205399||||FI|SME5
20180730|201807300000000005||50001521111200|0106276-4|5SIJ00|WIRE||EUR|EUR|20180730|20180730|||||||00000000000300.00|00000000000300.00|Credit||||||||||SIJ|||500015|506|||||||||||||||||||||||||FI3158410220205399||||FI|SME5
20180730|201807300000000006||50001521111200|0106276-4|5SIJ00|WIRE||EUR|EUR|20180730|20180730|||||||00000000000050.00|00000000000050.00|Credit||||||||||SIJ|||500015|506|||||||||||||||||||||||||FI3650005020017008||||FI|SME5
20180730|201807300000000007||50001521111200|0106276-4|5SIJ00|WIRE||EUR|EUR|20180730|20180730|||||||00000000000015.00|00000000000015.00|Credit||||||||||SIJ|||500015|506|||||||||||||||||||||||||FI1958410220026068||||FI|SME5
20180730|201807300000000008||50001521111200|0106276-4|5SIJ00|WIRE||EUR|EUR|20180730|20180730|||||||00000000000300.00|00000000000300.00|Credit||||||||||SIJ|||500015|506|||||||||||||||||||||||||FI8358410220212320||||FI|SME5

i)我想读取第一个文件的每一行,如果第二个文件中存在此“字符串”行,则会将第二个文件的整个事务放到一个新文件中。

ii)创建的这个新文件,我们将在每行中计算“ |”字符,如果每行中的字符数超过64,则会删除特定行中的61“ |”。

我设法完成了脚本的i)部分,但是我需要ii)部分的帮助。

到目前为止,我的i)部分有效的MY代码:

#!/bin/bash

while read line
do

grep "$line" /opt/TRANSACTIONS_DAILY_20180730.txt

done < /tmp/TRANSACTIONS_DAILY_20180730.txt > tmp/TRANSACTIONS_DAILY_NEW_20180730.txt

3 个答案:

答案 0 :(得分:0)

这是仅bash的答案,但请考虑阅读有关bash参数扩展的信息

if  [ ${a:60:1} == '|' ] ; then
   b="${a:0:60}${a:61}"
   # b is the new line shortened by removing 1 character.
   # the position starts counting from zero, length starts at 1
   # read about parameter expansion here:
   # 
fi

https://www.gnu.org/software/bash/manual/html_node/Shell-ParameterExpansion.html

答案 1 :(得分:0)

首先删除|工作。 您可以使用较小的测试文件进行测试:

$ cat testfile
Target: remove 4th | (after the 4) when 6 | are present.
1|2|3|4|5|6|7|8
1|2|3|4|5|6|7
1|2||4|5||7
1|2||4|5|6
1|2||4|5|

使用sed,您可以匹配诸如([^|]*[|])之类的正则表达式,并使用\1调用此正则表达式。
我已将管道放在括号[|]中,因此它不会被视为OR。
您不想重复该图案61次,因此您将制作一个包含重复数量的图案的图案。您需要注意记住字段的顺序:

$ echo "1|2|3|4|5|6|7|8" | 
   sed -r 's/(([^|]*[|]){3})([^|]*)[|](([^|]*[|]){2})(.*)/input=&\n1=\1\n2=\2\n3=\3\n4=\4\n5=\5\nrest=\6/'

在“一个字段”模式中使用可变符号可能会使命令更易于阅读:

$ p='([^|]*[|])'
$ echo "1|2|3|4|5|6|7|8" | 
   sed -r 's/('$p'{3})([^|]*)[|]('$p'{2})(.*)/input=&\n1=\1\n2=\2\n3=\3\n4=\4\n5=\5\nrest=\6/'

input=1|2|3|4|5|6|7|8
1=1|2|3|
2=3|
3=4
4=5|6|
5=6|
rest=7|8

当行中有足够的字段时,将更改行。我们忽略了匹配2和5。

$ echo "1|2|3|4|5|6|7|8" | sed -r 's/('$p'{3})([^|]*)[|]('$p'{2})(.*)/\1\3\4\6/'
1|2|3|45|6|7|8

第四个|已被删除。您也可以使用测试文件进行测试

$ sed -r 's/('$p'{3})([^|]*)[|]('$p'{2})(.*)/\1\3\4\6/' testfile
Target: remove 4th | (after the 4) when 6 | are present.
1|2|3|45|6|7|8
1|2|3|45|6|7
1|2||45||7
1|2||4|5|6
1|2||4|5|

当存在64个以上的|时,将命令修改为删除第61个$ testfile=tmp/TRANSACTIONS_DAILY_NEW_20180730.txt $ sed -r 's/('$p'{60})([^|]*)[|]('$p'{4})(.*)/\1\3\4\6/' ${testfile}

-f

第一部分(匹配两个文件)可以使用grep的$ grep -Ff /tmp/TRANSACTIONS_DAILY_20180730.txt /opt/TRANSACTIONS_DAILY_20180730.txt 选项来完成。 请尝试

$ sed -r 's/('$p'{60})([^|]*)[|]('$p'{4})(.*)/\1\3\4\6/' <(
   grep -Ff /tmp/TRANSACTIONS_DAILY_20180730.txt /opt/TRANSACTIONS_DAILY_20180730.txt
)

您可以将命令与

cut

编辑: 使用echo "WARNING: Slow while loop, demo purpose only." while IFS= read -r line; do p="${line//[!|]/}" np=${#p} if (( np > 5 )); then printf "%s%s\n" "$(cut -d'|' -f1-4 <<<"${line}")" "$(cut -d'|' -f5- <<<"${line}")" else printf "%s\n" "${line}" fi done < testfile 可以循环执行,但对大型文件而言效果不佳

sed -r

编辑:OP尝试编辑我的答案以及其他问题。他的Solaris系统不支持grep -fksh
我试图找到答案,但是没有在Solaris上进行测试。

在Solaris上使用bashwhile IFS= read -r line; do # count pipes in line using var p with only the pipes. # This can be handled wih "tr" as well, using # echo "${line}" | tr -cd "|" | wc -c p="${line//[!|]/}" np=${#p} if [ ${np} -gt 64 ]; then printf "%s%s\n" "$(echo "${line}" | cut -d'|' -f1-60)" "$(echo "${line}" | cut -d'|' -f61- )" else printf "%s\n" "${line}" fi done < tmp/TRANSACTIONS_DAILY_NEW_20180730.txt 可能适用于

var  data =   [
    {
        "_id": "5b658d37692f2e3c881960cb",
        "_MovieId": "5b5835dd86ab401494263861",
        "_TheaterId": "5b3dfeb217bc8c23f0e7ec3f",
        "dateTime": "2018-08-04T14:00:00.000Z",
        "showTakenSeats": {
            "0-0": "5b658f79dd8bb938289e2e0b",
            "0-1": "5b658f79dd8bb938289e2e0b",
            "0-2": "5b658f79dd8bb938289e2e0b"
        },
        "__v": 0,
    },
    {
        "_id": "5b658d4a692f2e3c881960cc",
        "_MovieId": "5b584eb186ab401494263868",
        "_TheaterId": "5b45d269a53b0c05f8959260",
        "dateTime": "2018-08-04T13:00:00.000Z",
        "showTakenSeats": {
            "0-0": "5b65904bdd8bb938289e2e0d",
            "0-1": "5b65904bdd8bb938289e2e0d",
            "0-2": "5b65904bdd8bb938289e2e0d"
        },
        "__v": 0,
    },
    {
        "_id": "5b658fd1dd8bb938289e2e0c",
        "_MovieId": "5b575452478afb72ec65f8f6",
        "_TheaterId": "5b45d219a53b0c05f895925f",
        "dateTime": "2018-08-04T20:00:00.000Z",
        "showTakenSeats": {},
        "__v": 0,
    },
    {
        "_id": "5b6593d80d48d9394877dd09",
        "_MovieId": "5b584eb186ab401494263868",
        "_TheaterId": "5b446a8768db4e2e980723ab",
        "dateTime": "2018-08-05T10:00:00.000Z",
        "showTakenSeats": {},
        "__v": 0,
    },
    {
        "_id": "5b65943b0d48d9394877dd0a",
        "_MovieId": "5b584eb186ab401494263868",
        "_TheaterId": "5b446a8768db4e2e980723ab",
        "dateTime": "2018-08-03T22:00:00.000Z",
        "showTakenSeats": {},
        "__v": 0,
    }
]


var withCount = data.map(function(e){
  return Object.assign({count: Object.keys(e.showTakenSeats).length}, e);
})

console.log(withCount);

答案 2 :(得分:0)

直到现在这段代码对我都有效:

代码:

#!/bin/bash
PATH=/usr/xpg4/bin:/bin:/usr/bin

while read line
do

grep "$line" /tmp/BadTransactions/test_data_for_validation_script.txt

awk 'NR==FNR { K[$1]; next } ($2 in K)' /tmp/BadTransactions/TRANSACTIONS_DAILY_20180730.txt FS="|" /opt/NorkomC
onfigS2/inbox/TRANSACTIONS_DAILY_20180730.txt > /tmp/BadTransactions/TRANSACTIONS_DAILY_NEW_20180730.txt

sed '/\([^|]*[|]\)\{65\}/ s/|//61' /tmp/BadTransactions/TRANSACTIONS_DAILY_NEW_20180730.txt

done < /tmp/BadTransactions/TRANSACTIONS_DAILY_20180730.txt > /tmp/BadTransactions/TRANSACTIONS_DAILY_NEW_201807
30.txt

所以直到现在,如果每行中有第64个以上的管道,它将删除第61个管道。

现在,如果该行具有64个以上的管道,则我希望删除每行中的第61个管道,直到该行达到整行中的64个管道为止

我的意思是:

例如,如果某行有67个管道,它将删除第61个管道,然后它将再次转到同一行,现在它将检查是否有64个以上的管道(实际上现在有66个管道),并且它将删除第61个管道。

这将一直持续到管道数超过64个为止。

您能建议我任何想法如何循环吗?

谢谢