awk sed if statement


9

Saya mencoba menambahkan 0 ke awal, JIKA ada "." pada karakter ke-2 dari baris itu. Saya tidak bisa menggabungkan keduanya;

awk '{ print substr( $0, 2, 1 ) }' file.txt 

menunjukkan karakter kedua

sed -ie "s/.\{0\}/0/" file.txt

menambahkan nol ke awal.

Harus ada "jika karakter kedua adalah titik".

file sampel:

1.02.2017 23:40:00
10.02.2017 23:40:00

terakhir:

01.02.2017 23:40:00
10.02.2017 23:40:00

Jawaban:


12

Kami dapat menggunakan salah satu sedatau awkuntuk sepenuhnya menyelesaikan masalah.


Dengan sed:

$ sed 's/^.\./0&/' file.txt

Ketika &terjadi di bagian penggantian dari perintah substitusi ( s), itu akan diperluas ke bagian dari garis input yang cocok dengan bagian pola dari perintah.

Ekspresi reguler ^.\.berarti " cocok dengan semua baris yang dimulai dengan ( ^) karakter arbitrer ( .) diikuti oleh titik literal ( \.) ".

Jika garisnya 1.02.2017 23:40:00, polanya akan cocok, dan 1.akan diganti dengan 01.di awal garis.


Dengan awk:

Membangun awkkode parsial dalam pertanyaan ...

Ini akan, seperti yang dinyatakan, mencetak karakter kedua dari setiap baris input:

$ awk '{ print substr($0, 2, 1) }' file.txt

Kita dapat menggunakan fakta yang substr($0, 2, 1)mengembalikan karakter kedua dan menggunakannya sebagai syarat:

$ awk 'substr($0, 2, 1) == "." { ... }' file.txt

Apa yang masuk ke dalam { ... }adalah kode yang diawali $0, yang merupakan isi dari baris saat ini, dengan nol jika kondisi sebelumnya benar:

$ awk 'substr($0, 2, 1) == "." { $0 = "0" $0 }' file.txt

Maka kita hanya perlu memastikan bahwa semua garis dicetak:

$ awk 'substr($0, 2, 1) == "." { $0 = "0" $0 } { print }' file.txt

Kondisi substr($0, 2, 1) == "."tentu saja dapat diubah menjadi ekspresi reguler juga (kami menggunakan ekspresi yang sama persis seperti yang kami gunakan dalam sedsolusi):

$ awk '/^.\./ { $0 = "0" $0 } { print }' file.txt

Beberapa orang yang berpikir "lebih pendek selalu lebih baik" akan menuliskannya sebagai

$ awk '/^.\./ { $0 = "0" $0 } 1' file.txt

(dan mungkin juga menghapus sebagian spasi: awk '/^.\./{$0="0"$0}1' file.txt)


1
+1 Contoh AWK terakhir Anda atau contoh sed Anda adalah cara yang benar untuk melakukan ini. Perhatikan, untuk kejelasan, bahwa itu hanya akan menjadi satu atau yang lain.
Dijeda sampai pemberitahuan lebih lanjut.

Menurut pendapat saya pendekatan "benar" (yang tidak mengutak-atik ruang dan yang lebih ringan pula) adalah versi final Anda sed 's/^.\./0&/' file.txt,. Saya pikir Anda harus meletakkan itu di awal jawaban ini. Tetap, +1.
Wildcard

1
@Wildcard Kami bertujuan untuk menyenangkan.
Kusalananda

5

Dengan sed:

sed -e "/^.\./s/^/0/" file.txt 

Pola /^.\./mencari karakter dan titik literal di awal baris ^, dan jika cocok, substitute yang memulai baris dengan nol, secara efektif menambahkan nol ke awal.

Sed expressoin s/.\{0\}/0/agak aneh, cocok dengan nol atau lebih salinan apa pun dan diganti dengan nol. Pola ini tentu saja akan cocok di setiap posisi string, tetapi karena s///hanya menggantikan pertandingan pertama, itu berfungsi seperti yang Anda inginkan. Namun, cara yang aneh untuk melakukannya.


Atau dengan awk, regex yang sama akan bekerja untuk mencocokkan garis, tetapi kita dapat menggunakan substr:

awk 'substr($0, 2, 1) == "." {$0 = "0" $0} 1' file.txt 

Kami pertama-tama menguji apakah karakter kedua adalah sebuah titik, kemudian tambahkan nol ke depan garis jika demikian. Yang terakhir memanggil tindakan standar mencetak garis setelah modifikasi.


4

Anda mengatakan awk dan sed, tetapi sepertinya Anda mencoba untuk memformat tanggal dan untuk itu saya akan menggunakan dateperintah. Contohnya:

echo '1.2.2017 23:40:00' | sed 's/\./\//g' | xargs -0 date '+%m.%d.%Y %T' -d

akan menampilkan

01.02.2017 23:40:00

The sedperintah di tengah perubahan periode ke garis miring untuk masukan ke date -d. Opsi format memungkinkan output di hampir semua format yang Anda inginkan. Secara %mkhusus akan nol pad bulan, yang sepertinya Anda coba lakukan.

Seperti yang ditunjukkan Kusalananda:

Bahkan lebih ringkas (tanggal GNU dan Bash): date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'


2
Tangkapan bagus! Bahkan lebih ringkas (tanggal GNU dan Bash):date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'
Kusalananda

Setiap kali saya punya garis miring dalam pola saya, tapi tidak ada Pipa: s|\.|/|g. Kalau tidak, seperti disebutkan di atas: Tangkapan bagus, +1
Alex Stragies

2

Strategi yang berbeda dari yang disajikan dalam jawaban lain: Anda bisa menggunakan "." sebagai pemisah bidang.

awk -F. '$1 < 10 {printf "0"} {print}' /tmp/in.txt

Anda bisa bermain golf ini ke:

awk -F. '$1<10{printf "0"}1' /tmp/in.txt

Untuk sed, ada perintah yang lebih pendek, disajikan dalam jawaban (bagus) lainnya.


1
Alternatif: awk -F. '{print ($1<10?0$0:$0)}' file
George Vasiliou

1

Dengan sed bisa jadi

sed 's/^\(.\)\.\(.*\)/0\1.\2/'

Ini akan digunakan ^untuk berlabuh ke awal baris, kemudian menangkap karakter tunggal dalam grup, diikuti oleh literal ., lalu hal lainnya. Jika kami cocok dengan yang kami cetak 0, maka grup tangkapan pertama kami (karakter di awal baris), lalu .grup tangkapan kedua kami (sisa baris)


Sama sekali tidak perlu melakukan penangkapan itu. &adalah temanmu Lihat contoh sed Kusalananda.
Dijeda sampai pemberitahuan lebih lanjut.

@DennisWilliamson tidak perlu, tetapi mengingat ada contoh lain yang sudah menunjukkan fitur lain sedyang dapat berguna dalam situasi lain, bukan hanya masalah khusus ini
Eric Renouf
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.