От удара (1):
ПСЕВДОНИМЫ
[...] первое слово каждой простой команды, если закрывшийся кавычки, проверяется, чтобы видеть, имеет ли это псевдоним [...] символы [...] и любой из метасимволов оболочки или упомянутых выше символов заключения в кавычки не могут появиться на имя псевдонима.
Таким образом, псевдонимы могут только быть отдельным словом без любых символов заключения в кавычки.
Использование обоих -f
и -i
в вызове к комнате также не имеет большого смысла, потому что они являются несколько противоречащими (комната (1)):
- f, - сила игнорирует несуществующие файлы и аргументы, никогда не запрашивает
- я запрашиваю перед каждым удалением
Но вот хорошая вещь - Ваш псевдоним к rm
на самом деле используется, даже когда Вы звоните rm -r
, потому что первое слово - rm
- имеет псевдоним - rm -i
, таким образом, это заменяется этим!
$ alias rm
bash: alias: rm: not found
$ alias rm='rm -i'
$ mkdir test
$ rm -r test
rm: remove directory ‘test’?
/ редактирование: Raphael Ahrens также упомянул в комментариях то использование -f
(сила) не необходима для удаления каталогов (как может быть уже замечен в моем примере), -r
достаточно (рекурсивный) является одним:
- r,-R, - рекурсивный удаляют каталоги и их содержание рекурсивно
In Perl
perl -F';' -lane 'push @{$h{join ";",@F[0..2]}},$F[3];
END{
for(sort keys %h){
print "$_: ". join ",",@{$h{$_}};
}
}' your_file
Вы должны уметь делать что-то подобное в awk
, используя ассоциативные массивы, но я не очень хорошо разбираюсь в awk
, так что я не могу внести реальный код.
Объяснение
Вот расширенная версия вышеуказанного кода, использующая как можно меньше "магии":
open($FH,"<","your_file");
while($line=<$FH>){ # For each line in the file (accomplished by -n)
chomp $line; # Remove the newline at the end (done by -l)
# The ; is set by -F and storing the split in @F done by -a
@F = split /;/,$line # Split the line into fields on ;
$app_id = join ";",@F[0..2]; # AppID is the first 3 fields
push @{$h{$app_id}},$F[3]; # The 4th field is added onto the hash
} # The whole file has been read at this point.
foreach $key (sort keys %h){ # Sort the hash by AppID
print "$key: " . join ",",@{h{$key}}."\n"; # Print the array values
# The newline ("\n") added at the end is also done by -l
}
Теперь осталось только утверждение push
, чтобы объяснить более подробно:
push
обычно используется для добавления элементов в переменную массива. Например:
push @a,$x
добавляет содержимое переменной $x
в массив @a
.
Цикл чтения файла построчно заполняет хэш-таблицу (%h
). Ключами к хэшу являются AppIDs, а значение, соответствующее каждому ключу, представляет собой массив, содержащий все идентификаторы пользователей, связанные с этим AppID. Это анонимный массив (у него нет имени); в Perl это реализовано в виде ссылки на массив (несколько похоже на указатели C). А так как значение %h
, соответствующее AppID $app_id
обозначается $h{$app_id}
, то при обращении к сигиальному массиву Perl (@
) хэш-значение рассматривается как массив (отсылка к ссылке на массив) и на него нажимается текущий идентификатор пользователя.
Альтернативой, которая может показаться вам менее "Perlish", будет соединение 4-го поля с текущим значением:
while(...) { ... $h{$app_id} = $h{$app_id} . ",$F[3]" }
foreach $key (клавиши сортировки %h) { распечатать "$_: $h{$_}") }
, где .
в Perl является оператором конкатенирования строк.
Обратите внимание, что в коде объяснения я опустил обертку perl -e '...'
, чтобы подсветка синтаксиса могла попасть в код и сделать его более читабельным.
Ответ: sed
:
sed ': l;N;s/^\([^;]\+;[^;]\+;[^;:]\+\)[;:] *\(.*\)\n\1;\(.*\)/\1: \2, \3/;tl;P;D' input_file.txt
Файл читается только один раз, так что производительность не должна быть слишком плохой, но я не могу сказать больше.
С подробностями:
sed ': l; # Label l
N; # Add next line of input to pattern space
s/^\([^;]\+;[^;]\+;[^;:]\+\)[;:] *\(.*\)\n\1;\(.*\)/\1: \2, \3/;
# If two lines in pattern space start with same AppID, then
# take user ID and append it to first line, then delete second line
tl; # If previous substitution succeeded, i.e. we scanned two lines with
# same AppID, then loop to label l. Else go on…
P; # Print first line from pattern space (here there should be two lines
# in pattern space, starting with a different AppID)
D; # Delete first line of pattern space; start script again with
# remaining text in pattern space, or next input line if pattern
# space is empty
' input_file.txt
(Но я понятия не имею о потенциальных ограничениях длины строк, извините.)
Поскольку вы утверждаете, что файл отсортирован, не следует ли использовать простой цикл с памятью только для предыдущей строки appId
? Это похоже на подход @Qeole sed
, но позволяет избежать накладных расходов на регулярные выражения, используя функцию shell's delimited read
plus string comparison:
#!/bin/bash
appId=""
while IFS=\; read -r s1 s2 s3 userId; do
if [ "$s1;$s2;$s3" == "$appId" ]; then
printf ', %s' "$userId"
else
appId="$s1;$s2;$s3"
printf '\n%s:%s' "$appId" "$userId"
fi
done < yourfile
printf '\n'
NOTE: это печатает дополнительную новую строку в начале вывода, но это может быть предотвращено с минимальной дополнительной сложностью. Бэш должен быть довольно быстрым для такого рода вещей, но если нет, то вы можете перевести его практически на любой похожий скриптовый язык.
Вот AWK
решение:
awk '10<=NR && NR<=15 && /pattern/ {print NR,$0}' file
Если мы должны использовать только SED
, затем рассмотрим:
sed -n '10,15 {/pattern/ {=;p}}' file | sed 'N;s/\n/ /'
SED =
Команда будет печатать только номер строки на отдельной строке. Второй случай SED
выше используется для объединения каждых двух линий, чтобы номер линии отображался незадолго до его линии.
С SED
:
sed 's/;/:\t/3;H;1h;x
s/^\(\([^:]*\):.*\)\n\2/\1/
/\n/P;//g;h;$!d' <input |
tr : \\n
, что печатается:
44a934ca4052b34e70f9cb03f3399c6f065becd0;bf038823f9633d25034220b9f10b68dd8c16d867;309
8ead5b3e0af5b948a6b09916bd271f18fe2678aa
a21245497cd0520818f8b14d6e405040f2fa8bc0
5c3eb56d91a77d6ee5217009732ff421e378f298;200000000000000001000000200000,6fd299187a5c347fe7eaab516aca72295faac2ad,e25ba62bbd53a72beb39619f309a06386dd381d035de372c85d70176c339d6f4;16
337556fc485cd094684a72ed01536030bdfae5bb
382f3aaa9a0347d3af9b35642d09421f9221ef7d
396529e08c6f8a98a327ee28c38baaf5e7846d14
Вы можете отбрасывать TR
, чтобы сохранить группы на одной линии. ID ID : :
толстой кишки в этом случае. Вам также может потребоваться заменить \ T
\ T
в первой строке с литералом
символ - или вы можете не стесняться удалить \ T
ABS полностью - они служат только для того, чтобы сделать выпуск более читаемым (на мой взгляд) и не имеет жизненно важной для функции регулярного воздействия.