, Как удалить Инверсию, соответствуют парам?

Если вам нужно отличить 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
2
07.09.2018, 06:46
3 ответа

Может быть, что-то вроде:

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
1
27.01.2020, 21:58

с помощью 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

Это устанавливает разделитель полей в вертикальной черте с необязательным начальным или конечным пробелом. Затем он ищет «пары» как ключи ассоциативного массива в любом порядке :, если они найдены, пропустите эту строку; в противном случае добавьте ключ в массив и напечатайте строку.

3
27.01.2020, 21:58

Вы можете сделать это с помощью 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| 
0
27.01.2020, 21:58

Теги

Похожие вопросы