Добавьте двойные кавычки, если между словами в столбце

Достаточно интересно, кажется, что ответ может быть: «Это зависит от обстоятельств».

Для ясности: mv указывается с до

Утилита mv должна выполнять действия, эквивалентные функции rename ()

В спецификации функции переименования говорится:

Эта функция rename () эквивалентна для обычных файлов функции , определенной стандартом ISO C. Его включение здесь расширяет определение , включая действия с каталогами, и определяет поведение , когда новый параметр называет уже существующий файл. Эта спецификация требует, чтобы действие функции было атомарным.

Но последняя спецификация ISO C для rename () гласит:

7.21.4.2 Функция переименовать

Краткое содержание

 #include  
int rename (const char * old, const char * new); 
 

Описание

Функция rename вызывает файл имя которой - строка, на которую указывает старый , отныне известная под именем , заданным строкой, на которую указывает new . Файл с именем старый больше не доступен с этим именем.Если файл, названный строкой, на которую указывает new , существует до вызова функции rename , поведение определяется реализацией.

Возвращает

Функция rename возвращает ноль, если операция завершается успешно, ненулевое значение в случае неудачи; в этом случае, если файл существовал ранее, он все еще известен под своим исходным именем.

Удивительно, но обратите внимание, что нет явного требования атомарности. Он может потребоваться где-то еще в последнем общедоступном стандарте C, но мне не удалось его найти. Если кто-то может найти такое требование, мы приветствуем правки и комментарии.

См. Также Является ли rename () атомарной?

Согласно странице руководства Linux :

Если newpath уже существует, он будет заменен атомарно, поэтому что не существует точки, в которой другой процесс, пытающийся получить доступ к newpath , не обнаружит, что он отсутствует. Однако, вероятно, будет окно , в котором оба oldpath и newpath относятся к переименованному файлу .

На странице руководства Linux утверждается, что замена файла будет атомарной.

Тестирование и проверка того, что атомарность может быть очень сложной, однако, если это то, насколько далеко вам нужно зайти. Вам непонятно, что вы имеете в виду, используя «Как я могу проверить, является ли mv атомарным».Вы хотите, чтобы требования / спецификация / документация были атомарными, или вам действительно нужно проверить это?

Также обратите внимание, что выше предполагает , что имена двух файлов операндов находятся в та же файловая система. Я не могу найти стандартного ограничения для утилиты mv , чтобы обеспечить это.

2
24.03.2017, 01:22
6 ответов
$ echo 'Unites State | California | UNIX | ABC DE' | sed -E 's/([^ |]+ +[^|]+)( +\||$)/"\1"\2/g'
"Unites State" | California | UNIX | "ABC DE"
  • Предполагается, что перед |
  • -E всегда есть пробел, используйте ERE, в некоторых sed версиях используется -r вместо
  • ([^ |] + + [^ |] +) непробельные, не- | символы, за которыми следует хотя бы один пробел, а затем не- | символы
  • (+ \ || $) вышеуказанный образец, за которым следует хотя бы один пробел, а затем | или конец строки
  • «\ 1» \ 2 цитата согласно требованию
1
27.01.2020, 22:03

из-за не могу комментировать, отвечаю здесь.

perl -pe 's/\w+\s+\w+/\"$&\"/g' 

более простой ответ Джорджа Василиу.

0
27.01.2020, 22:03

POSIXly:

sed 's/[^ |][^|]* [^|]*[^| ]/"&"/g'

Для учета других пустых символов, кроме пробела ASCII, используйте:

sed 's/[^[:blank:]|][^|]*[[:blank:]][^|]*[^|[:blank:]]/"&"/g'
1
27.01.2020, 22:03
TAB=`echo 'x' | tr 'x' '\011'`; # tab
SPC=`echo 'x' | tr 'x' '\040'`; # space
s="[$SPC$TAB]";                 # whitespace regex
W="[^|$TAB$SPC]";               # building block of a word
echo ' United  States   | California | UNIX|ABC DE' |
sed -e "s/\($W$W*$s$s*\)\{1,\}[^|][^|]*/\"&\"/g"
0
27.01.2020, 22:03

В Perl я бы на самом деле использовал split :

#!/usr/bin/env perl
use strict;
use warnings;

#iterate data block below (use <> for reading STDIN)
while ( <DATA> ) {
   #split on whitespace|whitespace
   my @fields = split /\s*\|\s*/;
   #transform individual fields
   for ( @fields ) { 
      #check if it contains a space
      next unless m/\s/;
      #if it does, quote
      s/(^|$)/\"/g;
   }
   #print output; 
   print join " \| ", @fields,"\n";
} 

__DATA__
Unites State | California | UNIX | ABC DE

Который выводит:

"Unites State" | California | UNIX | "ABC DE"

Но также справляется с полями, состоящими из нескольких слов.

Упростим это до однострочника, потому что все классные ребята:

perl -F'\s*\|\s*' -lane '/\s/&&s/(^|$)/\"/g for @F;print join " \| ",@F'
0
27.01.2020, 22:03

Неплохо с Perl:

echo $'Unites State | California | UNIX | ABC DE' |perl -pe 's/[a-zA-Z]+[[:space:]]+[a-zA-Z]+/\"$&\"/g'
"Unites State" | California | UNIX | "ABC DE"
1
27.01.2020, 22:03

Теги

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