Если вам нужно отличить ascii от utf, лучше всего использовать команду file
. man file
для подробностей.
Вот способ найти все файлы в текущем каталоге, имена которых имеют ascii или не ascii:
$ cat foo.sh
#!/bin/bash
echo "$1" > /tmp/name.txt
file /tmp/name.txt | grep -q $2
exit $?
$ find . -maxdepth 1 -type f -name \*txt -exec ./foo.sh {} UTF \; -a -print
./へ.txt
./robenbox_Probenkästen.txt
$ find . -maxdepth 1 -type f -name \*txt -exec ./foo.sh {} ASCII \; -a -print
./foo.txt
./log.txt
./utf8.txt
Вот мой первый ответ...
Таким образом:
$ find . -maxdepth 1 -type f -name \*txt -exec ./foo.sh {} ASCII \; -a -print
./ascii.txt
$ find . -maxdepth 1 -type f -name \*txt -exec ./foo.sh {} utf \; -a -print
./utf8.txt
$ cat foo.sh
#!/bin/bash
file $1 | grep -q $2
exit $?
Потому что:
$ cat ascii.txt
English is a West Germanic language that was first spoken in early medieval England and is now a global lingua franca.
$ cat utf8.txt
Texts written with Man'yōgana use two different kanji for each of the syllables now pronounced き ki, ひ hi, み mi, け ke, へ he, め me, こ ko, そ so, と to, の no, も mo, よ yo and ろ ro.
$ file ascii.txt
ascii.txt: ASCII text
$ file utf8.txt
utf8.txt: UTF-8 Unicode text
ken@ken-x230: ~$ od -c utf8.txt
0000000 T e x t s w r i t t e n w i
0000020 t h M a n ' y 305 215 g a n a u
0000040 s e t w o d i f f e r e n t
0000060 k a n j i f o r e a c h
0000100 o f t h e s y l l a b l e s
0000120 n o w p r o n o u n c e d
0000140 343 201 215 k i , 343 201 262 h i ,
0000160 343 201 277 m i , 343 201 221 k e ,
0000200 343 201 270 h e , 343 202 201 m e ,
0000220 343 201 223 k o , 343 201 235 s o ,
0000240 343 201 250 t o , 343 201 256 n o ,
0000260 343 202 202 m o , 343 202 210 y o a
0000300 n d 343 202 215 r o . \n
0000313
ken@ken-x230: ~$ od -c ascii.txt
0000000 E n g l i s h i s a W e s
0000020 t G e r m a n i c l a n g u
0000040 a g e t h a t w a s f i r
0000060 s t s p o k e n i n e a r
0000100 l y m e d i e v a l E n g l
0000120 a n d a n d i s n o w a
0000140 g l o b a l l i n g u a f
0000160 r a n c a . \n
0000167
Может быть, что-то вроде:
perl -F'[|]' -lane '
for (@F) {
# trim the fields to remove leading and trailing blanks
s/^\s+//; s/\s+$//
}
# re-join the trimmed fields into $a
my $a = join "|", @F[0..3];
# same, inverting the two pairs into $b
my $b = join "|", @F[2,3,0,1];
# print unless either $a or $b has been seen before
print unless $seen{$a} || $seen{$b}++' < your-file
Чтобы обобщить любое количество пар, найденных в любом порядке, вам нужно отсортировать эти пары, чтобы сделать ключ ассоциативного массива %seen
:
perl -F'[|]' -lane '
for (@F) {
# trim the fields to remove leading and trailing blanks
s/^\s+//; s/\s+$//
}
my @pairs;
while (my ($a, $b) = splice(@F, 0, 2)) {
push @pairs, "$a|$b"
}
my $key = join "|", sort @pairs;
print unless $seen{$key}++' < your-file
с помощью awk:
awk -F '[[:blank:]]*[|][[:blank:]]*' -v SUBSEP='|' '
($1,$2,$3,$4) in seen || ($3,$4,$1,$2) in seen {next}
{seen[$1,$2,$3,$4]; print}
' file
Это устанавливает разделитель полей в вертикальной черте с необязательным начальным или конечным пробелом. Затем он ищет «пары» как ключи ассоциативного массива в любом порядке :, если они найдены, пропустите эту строку; в противном случае добавьте ключ в массив и напечатайте строку.
Вы можете сделать это с помощью sed. В приведенном ниже коде используется gnu sed, но его можно легко сделать совместимым с posix.
sed -Ee '
$!{
s/$/|/
N
s/[[:blank:]]+//g
H;s/.*//;x;D
}
s/$/|/
G;H;g
y/\n_/_\n/
:xdup
s/_((([^_|]+[|]){2})(([^_|]+[|]){2}))_(.*_)?\4\2_/_\1_\6/
txdup
s/^_//;s/_$//
y/\n_/_\n/
' input.csv
По мере приближения часа пик объясню позже
Результаты:
10|Name1|20|Name2|
20|Name2|30|Name3|
40|Name4|30|Name3|