awk або sed для малого / верхнього регістру лише один символ у рядку?


13

Чи існує спосіб, як прописати лише великі літери лише в одному рядку?

Приклад введення:

syslog_apr_24_30
syslog_mar_01_17

Бажаний вихід:

syslog_Apr_24_30
syslog_Mar_01_17

Зверніть увагу, будь ласка, на початку місяця.

Я спробував, awkале я недостатньо хороший, щоб він працював.

Відповіді:


18

Ви можете використовувати \uв GNU sed для великих літер:

sed -e 's/_\(.\)/_\u\1/' input

Perl робить те ж саме:

perl -pe 's/_(.)/_\u$1/' input

\l робить навпаки.


8
На дотик простіше:sed 's/_./\U&/'
glenn jackman


3

Awk версія з підрядками та тупером

awk 'BEGIN{ FS=OFS="_"} {
        cap=toupper(substr($2,1,1));
        lower=substr($2,2,3);
        $2 = cap lower; print 
}' list.txt 

Проба зразка:

$ awk 'BEGIN{ FS=OFS="_"} { 
    cap=toupper(substr($2,1,1));
    lower=substr($2,2,3);$2 = cap lower; print 
}' list.txt               
syslog_Apr_24_30
syslog_Mar_01_17

3

Використання awk:

awk -F_ '{
    printf "%s_%s_%s_%s",$1,toupper(substr($2,1,1))substr($2,2,2),$3,$4"\n"
}' foo

або

awk -F_ '{
    for(i=1;i<=NF;i++) {
        if(i==2){
            printf "%s",toupper(substr($i,1,1))substr($i,2,length($i)-1)
        } 
        else {printf "%s",$i} 
        if(i<NF) {printf "%s","_"}
    } printf "%s","\n"}' foo

Приклад

% cat foo
syslog_apr_24_30
syslog_mar_01_17

% awk -F_ '{for(i=1;i<=NF;i++) {if(i==2){printf "%s",toupper(substr($i,1,1))substr($i,2,length($i)-1)} else {printf "%s",$i} if(i<NF) {printf "%s","_"}} printf "%s","\n"}' foo
syslog_Apr_24_30
syslog_Mar_01_17

% awk -F_ '{printf "%s_%s_%s_%s",$1,toupper(substr($2,1,1))substr($2,2,2),$3,$4"\n"}' foo 
syslog_Apr_24_30
syslog_Mar_01_17

3

Ось підхід Perl:

$ perl -pe 's/_./uc($&)/e' file
syslog_Apr_24_30
syslog_Mar_01_17

-pЗмушує кожен рядок друкується після застосування сценарію дається -e. Підстановка замінює перший екземпляр _і персонаж, що слідує за ним із самим собою ( $&незалежно від того, що було узгоджено) у верхньому регістрі ( uc()), eв кінці оператора підстановки ( s///e) потрібен для оцінки виразів.



1

Pure Bash 4.x, використовуючи регулярний вираз, щоб вибрати частину, яку ви хочете змінити, і ^^оператора набірних матеріалів на цій частині. Натискання спереду та ззаду (відповідність. *) Для відновлення цілого рядка:

foo=syslog_apr_24_30
if [[ $foo =~ (.*)(_[a-z])(.*) ]]; then
    foo=${BASH_REMATCH[1]}${BASH_REMATCH[2]^^}${BASH_REMATCH[3]}
fi

Якщо ви не пам’ятаєте всіх правил цитування, сміливо цитувати все, крім регулярного виразу (що дозволило б =~виконати буквальну відповідність рядків).

Оператор ^upcase-first працює лише на початку змінної (або елемента масиву). І, здається, немає розширення підрядків, яке дає вам те, що perl буде називати lvalue (яке ви можете призначити / змінити). Оператори "up / downcase" можуть приймати шаблон, який відповідає по символам, але це не допомагає пропустити syslog_, оскільки в "syslog" є імена місяця, що починаються з символів.

У будь-якому випадку, це може бути швидше, ніж foo="$(echo "$foo" | sed 's/_./\U&/')"(розміщено як коментар до прийнятої відповіді, Гленн Джекман).

Bash, sed або awk будуть МНОГО разів швидшими за перл. Якщо ви почнете знаходити декілька perl-вкладишів perl, корисних у сценарії оболонки, вам слід просто написати цілу справу в perl.


0

Якщо місяць завжди слідує за першим «_» (підкреслення), тоді використовуйте це (як показано в інших відповідях):

sed -e 's/_\(.\)/_\u\1/'

Якщо можуть бути інші підкреслення перед попереднім місяцем, то вищезгадане не спрацює.

Якщо місяць завжди починається з 8-го символу, то використовуйте це:

sed -e 's/^\(.\{7\}\)\(.\)/\1\u\2/'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.