Câu trả lời:
echo "syslog_apr_24_30" |
awk -F'_' '{print $1"_"toupper(substr($2,1,1)) substr($2,2) "_"$3"_"$4}'
Awk
phiên bản với chất nền và toupper
awk 'BEGIN{ FS=OFS="_"} {
cap=toupper(substr($2,1,1));
lower=substr($2,2,3);
$2 = cap lower; print
}' list.txt
Chạy mẫu:
$ 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
Sử dụng awk
:
awk -F_ '{
printf "%s_%s_%s_%s",$1,toupper(substr($2,1,1))substr($2,2,2),$3,$4"\n"
}' foo
hoặc là
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
Thí dụ
% 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
Đây là một cách tiếp cận Perl:
$ perl -pe 's/_./uc($&)/e' file
syslog_Apr_24_30
syslog_Mar_01_17
Các -p
nguyên nhân mỗi dòng được in sau khi áp dụng tập lệnh được đưa ra bởi -e
. Sự thay thế thay thế thể hiện đầu tiên _
và ký tự theo sau nó với chính nó ( $&
là bất cứ thứ gì được khớp) ở trên ( uc()
), e
ở cuối toán tử thay thế ( s///e
) là cần thiết để đánh giá các biểu thức.
Pure Bash 4.x, sử dụng regex để chọn ra phần bạn muốn incase và ^^
toán tử upcase trên phần đó. Xử lý ở mặt trước và mặt sau (khớp với. *) Để tạo lại toàn bộ chuỗi:
foo=syslog_apr_24_30
if [[ $foo =~ (.*)(_[a-z])(.*) ]]; then
foo=${BASH_REMATCH[1]}${BASH_REMATCH[2]^^}${BASH_REMATCH[3]}
fi
Nếu bạn không nhớ tất cả các quy tắc trích dẫn, sẽ an toàn khi trích dẫn mọi thứ trừ regex (điều này sẽ tạo ra =~
một chuỗi khớp theo nghĩa đen).
Các ^
nhà điều hành upcase đầu tiên chỉ hoạt động vào đầu của một biến (hoặc phần tử mảng). Và dường như không có bất kỳ sự mở rộng chuỗi con nào cung cấp cho bạn cái mà perl sẽ gọi là một giá trị (mà bạn có thể gán cho / sửa đổi). Các toán tử đầu tiên lên / xuống có thể lấy một mẫu phù hợp trên cơ sở mỗi ký tự, nhưng điều đó không giúp bỏ qua syslog_
, bởi vì có những tên tháng bắt đầu bằng các ký tự trong "syslog".
Dù sao, điều này có thể nhanh hơn foo="$(echo "$foo" | sed 's/_./\U&/')"
(được đăng dưới dạng bình luận cho câu trả lời được chấp nhận, bởi Glenn Jackman).
Bash, sed hoặc awk sẽ nhanh hơn NHIỀU lần so với perl. Nếu bạn bắt đầu tìm thấy nhiều perl một liners hữu ích trong tập lệnh shell, bạn chỉ nên viết toàn bộ trong perl.
Nếu tháng luôn theo sau "_" đầu tiên (gạch dưới), thì hãy sử dụng giá trị này (như thể hiện trong các câu trả lời khác):
sed -e 's/_\(.\)/_\u\1/'
Nếu có thể có dấu gạch dưới khác trước một tháng trước thì những điều trên sẽ không hoạt động.
Nếu tháng luôn bắt đầu bằng ký tự thứ 8, thì hãy sử dụng:
sed -e 's/^\(.\{7\}\)\(.\)/\1\u\2/'
sed 's/_./\U&/'