Yanıtlar:
-F
Seçenek bir argüman gerekir: -F,
örneğin.
awk
Komut dosyasının sonu , parametrelerin geri kalanıyla birlikte bir (boşluk karakteri) ile ayrılmalıdır .
Alan ayırıcı ise ,
ve bunu korumak istiyorsanız ve sütun sayısı sabit ve 11'e eşit veya daha düşükse, şunu deneyin:
awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"
command file > newfile && mv newfile file
. Yani GNU yeni bir sürümü söyledi awk
bunu desteklemek için: gawk -i inplace '{blah blah}' file
.
mv newfile file
kullanabilirsiniz cat newfile > file ; rm -f newfile
- bu inode ve izinlerini korur file
.
mktemp
geçici dosya adlarını komut dosyalarına kodlamak yerine kullanmak genellikle iyi bir fikirdir . örneğintf=$(mktemp) ; command file > "$tf" ; cat "$tf" > file ; rm -f "$tf"
Daha kısa çözüm
awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file
,+
Tüm awk
sürümlerde çalışıp çalışmayacağından emin değilim , ancak en azından GNU -c
awk'de , aynı zamanda uyumluluk modunda çalışıyor.
Açıklama:
$(NF+1)=$7
: önce satırın sonuna 7. alan ekliyoruz ( $12=$7
bu durumda olabilir)$7=""
: sonraki adımda 7. alan silinir (ancak çevresindeki sınırlayıcılar kalır)$0=$0
birden çok virgülün alan ayırıcısı olarak ele alındığı tüm kaydı (yoluyla ) yeniden ayarlamamız gerekir (bu -F',+'
, burada +
bir veya daha fazla kez yapılır) ve ayrıca $1=$1
önceden ayarlanmış çıktı alanını kullanarak satırı yeniden oluşturmaya zorlamak için geçerli kaydı yeniden düzenlememiz gerekir. ayırıcı (bir seçenekle ayarlanır -v OFS=,
)1
Örnek girdi:
1,2,3,4,5,6,7,8,9,10,11
çıktı
1,2,3,4,5,6,8,9,10,11,7
,+
çalışmalıdır.
all,ball,call,,,fall
→ all,ball,call,fall
). (2) $(NF+1)=$7
akıllı bir yaklaşımdır. IMHO, $0 = $0 OFS $7
biraz daha net, sadece birkaç karakter daha uzun ve aynı şeyi yapıyor gibi görünüyor. Kodunuzla $0 = $0 OFS $7
aynı şeyi yapmayan bir durum düşünebiliyor musunuz?
$0=$0 OFS $7
büyük olasılıkla aynıdır $(NF+1)=$7
, ancak genel olarak değil, yalnızca kodun geri kalanında değişiklik olmaz.
OFS=
Alanlarla ayırıcı olmadan yazdırıyorsanız , $7
bir değişkenin değerini kolayca kaydedebilir, $7
boş olarak ayarlayabilir ve çizgiyi ve değişkeni doğrudan yazdırabilirsiniz. Tüm alanları belirtmenize gerek yoktur:
$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file
12345687
Muhtemelen demek istediniz:
awk -F, -v OFS='' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' "$file"
awk
Tek tırnakları hiç görmediğini biliyorsun OFS=''
, değil mi? Sadece yazabilirsiniz OFS=
; tamamen aynı.
Özellikle awk kullanmak istediğinizi söylemediniz ve tarafından sağlanan düzenlemeyi kullanmak istediğinizi söylediniz sed -i
, işte bir sed -i
varyant. Genellikle awk
sütunlarla çalışmak için daha iyidir, ancak bu tercih ettiğim bir durumdur sed
, çünkü doğal olarak rasgele sayıda sütun işler.
MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/\1\4,\3/" -i test.csv
Açıklama:
-r
genişletilmiş normal ifadeleri seçer, böylece çok fazla ters eğik çizgiden kaçınırızTabii ki bu, virgülleri tırnak içinde saklayan (veya daha da kötüsü, onlardan kaçan) dosyalarla çalışmaz, ancak awk bazı ciddi akrobasi olmadan da bunu yapmaz. Eğer böyle bir sorun varsa birlikte daha iyi olurdu perl
modülü Text:CSV
veya python
modül csv
.
Birkaç awk
varyant (dosyanızın değişkenin içinde olduğu varsayılarak $file
)
Burada tüm sütunlar için döngü yapabilir, alan ayırıcısı (OFS) ile yazdırabilir ve satır sonundaki kayıt sonlandırıcıyı (ORS) yazdırabilirsiniz.
awk -F',' -v OFS=, \
'{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
printf "%s",$7;printf ORS}' "$file"
Burada bir normal ifade ve gensub()
işlev kullanarak
gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"
öldürme 7 inci alanını ve satırın sonunda yazdırmadan.
$0
tüm kayıt $n
n inci rekor NF
geçerli satırın Alan Sayısıdır OFS
çıktı dosyalanmış ayırıcıORS
çıkış kayıt sonlandırıcısı1
awk true
ve default ( $0
) yazdırmak için söyleyecek hiledir .Güncelleme ...
Neredeyse 7'den aşağıdaki tüm sütunları kayması mümkündür, unutmak inci biri.
awk -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"
OFS $7
daha sağlam olurdu "," $7
. (2) ", " $7
Sorunun OP'nin virgüllerden sonra boşluk istemediğini belirttiği sürece bunun yanlış olduğuna inanıyorum . (Ve, giriş verilerinde virgüllerden sonra boşluklar $7
olsaydı, zaten bir boşlukla başlayacaktı ve fazladan bir tane ekleyecektin.)
OFS $7
sadece daha sağlam değil, daha da genel ( "acele atık yapar" )
^
Hata ile karşılaşıldı komutların özel bölümünü gösterir.