我有一个名为 input.txt
的输入文件,如下所示:
powerOf|creating new file|failure
creatEd|new file creating|failure
powerAp|powerof server|failureof file
我将文本提取到第一个字段中第一个大写字母之前,并将这些片段存储在 output.txt
中:
power
creat
我使用 sed
命令来分离值,它工作正常。
从输出文件 (output.txt
),我需要从第一个字段grep
,输出应该如下所示:
Power
power:powerOf|creating new file|failure,powerAp|powerof server|failureof file
creat
creat:creatEd|new file creating|failure
我尝试了几种方法,但没有得到预期的输出。
我尝试了以下方法,但我得到了重复的条目:
cat input.txt | cut -d '|' f1 >> input1.txt
cat input1.txt | s/\([a-z]\)\([A-Z]\)/\1 \2/g >> output.txt
while read -r line;do
echo $ line
cat input.txt |cut -d ‘|’ f1|grep $line >> output1. txt
done< "output.txt"
我在输入文件中有 20000 行。我不知道为什么我会得到重复的输出。我做错了什么?
最佳答案
Bash 解决方案:
#!/bin/bash
keys=()
declare -A map
while read line; do
key=$(echo ${line} | cut -d \| -f1 | sed -e 's/[[:upper:]].*$//')
if [[ -z "${map[$key]}" ]]; then
keys+=(${key})
map[$key]="${line}"
else
map[$key]+=",${line}"
fi
done
for key in ${keys[*]}; do
echo "${key}"
echo "${key}:${map[$key]}"
done
exit 0
也许 Perl 解决方案也适用于 OP:
#!/usr/bin/perl
use strict;
use warnings;
my @keys;
my %map;
while (<>) {
chomp;
my($key) = /^([[:lower:]]+)/;
if (not exists $map{$key}) {
push(@keys, $key);
$map{$key} = [];
}
push(@{ $map{$key} }, $_);
}
foreach my $key (@keys) {
print "$key\n";
print "$key:", join(",", @{ $map{$key} }), "\n";
}
exit 0;
使用给定的输入进行测试:
$ perl dummy.pl <dummy.txt
power
power:powerOf|creating new file|failure,powerAp|powerof server|failureof file
creat
creat:creatEd|new file creating|failure
UPDATE 在 OP 重述原始问题后。第一个循环的解决方案只包括输入的第二列而不是整行:
message=$(echo ${line} | cut -d \| -f2)
if [[ -z "${map[$key]}" ]]; then
keys+=(${key})
map[$key]="${message}"
else
map[$key]+=",${message}"
fi
使用给定的输入进行测试:
$ perl dummy.pl <dummy.txt
power
power:creating new file,powerof server
creat
creat:new file creating
关于linux - 需要有关 shell 脚本的帮助以获得预期输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54457521/