Home Php C# Sql C C++ Javascript Python Java Go Android Git Linux Asp.net Django .net Node.js Ios Xcode Cocoa Iphone Mysql Tomcat Mongodb Bash Objective-c Scala Visual-studio Apache Elasticsearch Jar Eclipse Jquery Ruby-on-rails Ruby Rubygems Android-studio Spring Lua Sqlite Emacs Ubuntu Perl Docker Swift Amazon-web-services Svn Html Ajax Xml Java-ee Maven Intellij-idea Rvm Macos Unix Css Ipad Postgresql Css3 Json Windows-server Vue.js Typescript Oracle Hibernate Internet-explorer Github Tensorflow Laravel Symfony Redis Html5 Google-app-engine Nginx Firefox Sqlalchemy Lucene Erlang Flask Vim Solr Webview Facebook Zend-framework Virtualenv Nosql Ide Twitter Safari Flutter Bundle Phonegap Centos Sphinx Actionscript Tornado Register | Login | Edit Tags | New Questions | 繁体 | 简体


10 questions online user: 3

0
votes
answers
46 views
+10

「mkdir || echo && exit」即使mkdir成功退出

0

mkdir $ 2 ||回聲「我無法創建目錄$ 2」 & &出口8「mkdir || echo && exit」即使mkdir成功退出

大家好,這是我在這裏的第一篇文章,所以要善良。

我正在製作一個腳本,現在這條線困擾着我。

只有在無法創建目錄$ 2時纔會出現8號出口。 運行腳本併成功創建該目錄後,它仍然在8上退出。

我錯過了什麼嗎?我認爲只有在左側出現錯誤時,「||」後面的命令纔會發生。

我是Linux界的新手,作爲一個具有中小C經驗的人,我很困惑,幫忙! (使用Ubuntu,慶典,順便說一句)

+2

我認爲這是因爲運營商的優先。你可以放圓括號。如果mkdir失敗,則執行echo並返回true,以便執行第三個命令。也許你可以使用括號 – fernand0

+2

他是來自Unix和Linux SE的答案:https://unix.stackexchange.com/questions/88850/precedence-of-the-shell-logical-operators –

沙发
0
4

正如@ fernand0建議,問題是||&&符的優先級。您希望它運行類似mkdir || (echo && exit)的東西 - 即,如果mkdir失敗,則運行echo && exit部件。但是它實際上做的是運行類似(mkdir || echo) && exit的東西 - 也就是說,如果mkdirecho命令成功,它將運行exit部件。 echo幾乎總會成功,所以它幾乎總是會退出。

因此,您需要明確地對命令進行分組,以覆蓋此優先級。但不要使用(),因爲它在子shell中運行其內容,並且exit將僅僅退出子shell,而不是主腳本;您可以改爲使用{ },也可以使用明確的if塊。另外,您實際上不需要echo && exit,因爲只有在echo命令成功時才運行exitecho幾乎總是成功,但在罕見的情況下,它失敗了,我敢肯定你想腳本退出。

當我需要做這樣的事情在腳本中,我通常使用這個成語:

mkdir "$2" || { 
    echo "I can't create directory $2" >&2 
    exit 8 
} 

(注:如@CharlesDuffy建議,我加了周圍$2雙引號 - 雙引號變量如果它們包含任何空格,通配符等,引用幾乎總是一個好主意。我也送錯誤消息到標準錯誤(>&2),而不是標準輸出,這也是通常一個更好的方式來做事)

如果你想成爲更簡潔,你可以把它全部在一行。

mkdir "$2" || { echo "I can't create directory $2" >&2; exit 8; } 

注意,最終;(或換行)的}之前需要,或shell認爲}只是一個參數exit。你也可以去其他的方式,並使用一個明確的if塊:

if ! mkdir "$2"; then 
    echo "I can't create directory $2" >&2 
    exit 8 
fi 

這個選項是一樣聰明,簡潔的,但是這是一件好事 - 巧妙而簡潔的到底是什麼造成了首位這個問題;清晰明確的代碼更好。

+0

@CharlesDuffy完成! –

+0

你知道我有多愛你嗎?另外,你能幫我解決這個問題:> var = $(file -b $ 1 | grep「ISO」) 我在腳本中有這一行。如果文件失敗(例如:當沒有參數時),我收到一條關於它的用法的巨大錯誤消息。如何使用2>將該錯誤消息發送到/ dev/null?我嘗試了幾個選項,但都沒有工作。 – NuSuntStudent

+0

@NuSuntStudent你需要重定向打印錯誤命令的stderr,所以'var = $(file -b「$ 1」2>/dev/null | grep「ISO」)''。請注意,我還在'$ 1'周圍添加了雙引號,這會將錯誤消息更改爲關於未找到沒有名稱的文件。我建議在腳本的開頭添加腳本參數的健全性檢查(例如'if [-z「$ 1」];然後echo「Usage:...」>&2; exit 1; fi')。這允許您給出一個描述性錯誤,而不是用戶必須從腳本的哪些部分失敗中找出哪些問題。 –

板凳
0
-1

嘗試:

mkdir $1 
if [ $? -ne 0 ] ; then 
    echo "I can't create directory $1" 
    exit 8 
fi 
+1

這裏的降價引擎不是Github-flavored - 三重引號不會創建塊。在選擇多行代碼區域時,使用編輯器中的「{}」按鈕創建的四格縮進。 –

+1

不必要地測試'$?'是不好的形式。更好地寫'如果! mkdir「$ 1」;那麼' - 這樣,額外的日誌記錄或其他代碼更改就無法將您想要測試的操作與檢查本身解耦。 –

地板
0
1

||&&沒有你習慣於在其他語言的優先級。沒有語法化,它相當於(a || b) && c(嚴格爲從左到右),而不是a || (b && c)(其中&&||具有更高的優先級)。將命令與||&&混合在一起並不是一個好主意;而是使用if語句。

if ! mkdir "$2"; then 
    echo "I can't create directory $2" >&2 
    exit 8 
fi 

如果你真的想用列表的運營商,使用{ ... }到組適當的命令。

mkdir "$2" || { echo "I can't create directory $2" >&2; exit 8; } 
+2

'echo && exit'是不好的形式 - 如果'echo'失敗,我們真的想避免退出嗎?這應該是'mkdir「$ 2」|| {echo「...」>&2; 8號出口; }' –

+0

同意,雖然如果簡單的'echo'失敗了,你可能有更大的問題需要解決。 – chepner

0
votes
answers
31 views
+10

分號用雙引號字符串分割多個命令嗎?

-2

命令分號用雙引號字符串分割多個命令嗎?

cd /tmp; echo Hello 

產生

Hello 

引用,命令

"cd /tmp; echo Hello" 

產生

-bash: cd /tmp; echo Hello: No such file or directory 

任何想法,爲什麼會是這樣?我試圖使用引號,以便我可以建立一個命令鏈並通過ssh傳遞給遠程主機。謝謝。

沙发
0
1

行情沒有定義字符串;他們定義了單詞,因此在這種情況下,您的命令只包含一個單詞(除了;之外,還包含大量空白)。命令行中的第一個(非賦值)單詞被視爲命令的名稱,導致出現錯誤。

ssh以不同的方式工作,因爲整個字符串被傳遞給遠程端上的第二個 shell以再次進行評估。就像您可以在本地主機上運行sh -c "cd /tmp; echo hello"一樣,以下兩個命令大致相同:

ssh host "cd /tmp; echo hello" 
ssh host sh -c "cd /tmp; echo hello" 
板凳
0
-1

分號在雙引號內解釋。 更多解釋不能在這裏找到https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html

0
votes
answers
65 views
+10

Bash和Awk奇怪行爲(DD-WRT)

0

我正在DD-WRT Web界面中測試一個隨機化路由器MAC地址的小腳本。該腳本使用awk進行隨機化。這個腳本在awk被使用的時候起作用沒有 shebang(#!/ bin/bash),反之亦然(沒有awk但是包括shebang)。但是,當使用shebang awk時,該腳本不起作用。Bash和Awk奇怪行爲(DD-WRT)

作品(使用awk的,但沒有家當):

nvram set mac_clone_enable=1; 
nvram set def_hwaddr=$(awk 'function m(n){srand(systime()+n);return":"(10+int(rand()*99));}END{print "A4"m(1)m(2)m(3)m(4)m(5);}'); 
nvram commit; 
rc restart; 

也可以(有家當,但沒有AWK):

#!/bin/bash 

nvram set mac_clone_enable=1; 
nvram set def_hwaddr="02:44:55:66:77:88"; 
nvram commit; 
rc restart; 

不起作用(家當和awk):

#!/bin/bash 

nvram set mac_clone_enable=1; 
nvram set def_hwaddr=$(awk 'function m(n){srand(systime()+n);return":"(10+int(rand()*99));}END{print "A4"m(1)m(2)m(3)m(4)m(5);}'); 
nvram commit; 
rc restart; 

我需要腳本來使用awk並擁有shebang,因此它可以用於cron作業。可能是什麼問題呢?

+2

wrt'腳本無法正常工作 - 告訴我們它不工作的方式 - 錯誤的輸出,沒有輸出,核心轉儲,錯誤信息等等......當您要求機械師幫助診斷問題時希望你的車不要只指着你的車,並說「這行不通,可能是什麼問題?」。 –

+0

@EdMorton當MAC地址不起作用時,它沒有被更改。用戶karakfa提供了一個解決方案。 – user3163495

+0

如果這是問題,那麼你說的解決方案實際上不可能適用於相同的awk版本。我懷疑真正的問題是,你在每個腳本中調用不同版本的awk,如果你不這樣做,那麼它會在以後回來咬你;現在就調試它。 –

沙发
0
1

awk正在等待輸入文件。你可以重寫,而不是使用BEGIN

awk 'function r() {return ":"(10+int(rand()*99))} 
    BEGIN{srand(); print "A4" r() r() r() r() r()}' 

返回

A4:72:63:62:91:102 

你也不需要重新初始化每次隨機種子;一次就夠了。

0
votes
answers
59 views
+10

Python在運行啓動代理重新啓動後沒有運行Shell命令

1

因此,我通過啓動代理在macOS 10.13上啓動Python(2.7)腳本。腳本運行,並在執行過程中觸發計算機的重新啓動。當計算機重新啓動並登錄時,啓動代理再次運行該腳本。該腳本讀取日誌,然後執行切換:從中斷的地方繼續。Python在運行啓動代理重新啓動後沒有運行Shell命令

問題是,重新啓動後,python腳本無法執行某些shell命令。 ls -l工作正常。但是,當我嘗試運行不在/ bin中的內容時,似乎只是...跳過它。沒有錯誤,它根本就沒有做到。

下面是相關的代碼。我已經刪除了大部分細節以及開關控制,因爲我已經驗證了它們獨立工作。

#!/usr/bin/python 

import logging 
import os 
import subprocess 
import time 

#globals 
path_to_plist = 'User/Me/Library/Preferences/PathTo.plist' 


def spot_check(): 
    #determine where we are in the test, verified it works 
    return loop_number 

def func_that_checks_stuff(): 
    results = subprocess.check_output(['System/Library/Path/To/tool','-toolarg']) 
    ###process results 
    logging.info(results) 

def restarts(power_on, power off): 
    #sets plist key values for the restart app 
    subprocess.Popen('defaults write {} plist_key1 {}'.format(path_to_plist, power_on), shell=True 
    subprocess.Popen('defaults write {} plist_key2 {}'.format(path_to_plist, power_off), shell=True 

    #run the restart app, which is a GUI application in /Applications 
    logging.info('Starting restart app') 
    subprocess.Popen('open -a RestartApp.app', shell=True) 
    time.sleep(power_on + 5) 

def main(): 
    ###setup and config stuff, verified its working 

    #switch control stuff, verified its working 
    loop = spot_check() 

    if loop == 0: 
     #tool that shows text on the screen 
     subprocess.Popen('User/Me/Library/Scripts/Path/To/Text/tool -a -args', shell=True) 
     logging.info('I just ran that tool') 
     subprocess.check_output('ls -l', shell=True) 
     restarts(10, 0) 
    if loop == 1: 
     func_that_checks_stuff() 
     subprocess.Popen('User/Me/Library/Scripts/Path/To/Text/tool -a args', shell=True) 
     logging.info('Hey I ran that tool again, see?') 
     restarts(10, 0) 
    else: 
     func_that_checks_stuff() 
     subprocess.Popen('User/Me/Library/Scripts/Path/To/Text/tool -a args', shell=True) 

    print 'You finished!' 

if __name__ == '__main__': 
    main() 

因此,如果我使用我的啓動代理啓動它,它將運行通過每個序列就好了。

  • 在第一個循環(重新啓動之前),一切工作。所有日誌記錄,所有工具,一切。
  • 重啓後,所有的日誌工作,所以我知道它是跟隨開關控制。 func_that_checks_stuff()的作品,並記錄它的輸出正確。 ls -l' call shows me exactly what I should see. But,路徑/到/文本/工具doesn't run, and when I call重新啓動()`,它永遠不會打開應用程序。
  • 沒有錯誤,產生至少我能找到

我在做什麼錯?這與工具路徑有關嗎?

沙发
0
0

更新:

事實證明,解決辦法是在腳本的開頭添加約20秒的延遲。看起來它試圖在Window Server完成加載之前運行有問題的命令,並且將所有內容都嚇壞了。不是一個特別優雅的解決方案,但它適用於我在這個項目中需要的東西。

0
votes
answers
69 views
+10

根據日期範圍創建一組文件

0

如何在Bash中執行幾行代碼來完成以下操作。我試圖在Bash中建立我的技能,並學習如何從命令行處理更多的小任務目錄。根據日期範圍創建一組文件

步驟:

  1. 指定的開始日期和結束日期。將包含開始日期和結束日期之間的所有日期加載到「列表」中

  2. 循環遍歷列表,每次創建一個像這樣的文件。 (需要的日期格式)

    2017-11-10.w 
    2017-11-11.w 
    2017-11-12.w 
    
+0

Bash是不是管理日期很大。我會用Perl或其他更「高級」的語言來做,而不是bash。我的2美分。你試過什麼,研究什麼? – Nic3500

沙发
0
1

您可以將輸入的日期爲Unix的時間戳,然後添加的每一天,touch,直到你過去的結束日期的結果命名的文件的秒數:

#!/bin/bash 

startstamp=$(date -d "$1" +'%s') 
endstamp=$(date -d "$2" +'%s') 

secs_per_day=$((24 * 3600)) 

for ((thedate = startstamp; thedate <= endstamp; thedate += secs_per_day)); do 
    touch "$(date -d "@$thedate" '+%F.w')" 
done 

%s格式化字符串(GNU擴展)打印的自Unix紀元秒@在參數到-d選項的數量,並且表示該日期是在第格式。 %F%Y-%m-%d的縮寫,翻譯爲YYYY-MM-DD。

用法示例:

$ ./dates 2017-11-10 2017-11-15 
$ ls -1 
2017-11-10.w 
2017-11-11.w 
2017-11-12.w 
2017-11-13.w 
2017-11-14.w 
2017-11-15.w 
dates 
0
votes
answers
62 views
+10

如何運行bash腳本並設置變量?

0

我想運行一個bash腳本並在一個命令中設置變量。這可能嗎?如何運行bash腳本並設置變量?

bash wp.sh dbname="hello",dbuser="admin" 

這不適合我,我似乎無法找到任何指導。在此先感謝您的幫助!

+0

類似,但不完全相同的副本:https://stackoverflow.com/questions/7128542/how設置爲環境變量的僅限於該腳本的持續時間 –

沙发
0
2

要設置將由腳本進程繼承的環境變量,把分配開頭:

dbname="hello" dbuser="admin" bash wp.sh 
+0

非常感謝!那樣做了。只要它讓我把這個標記爲正確的答案(大約10分鐘),我會的。非常感激! :) –

+2

您的其他選項是將這些值作爲命令行參數處理,但這需要修改腳本以正確接受它們。有時候只是簡單的事情。 –

0
votes
answers
49 views
+10

CDPATH配置但不工作

1

我一直在試圖配置CDPATH變量,以包含一些具有長絕對路徑的目錄,放置在外部驅動器上,但儘管告訴我目錄包含在內,'cd'命令沒有更改目錄無論哪種方式
我用下面的命令:CDPATH配置但不工作

$ export CDPATH=/media/user/01/workspace/rubystudies
然後
$ echo $CDPATH,這回我下面的:

/media/user/01/workspace/rubystudies
然而,當我嘗試cd rubystudiescd /rubystudies它說
bash: cd: /rubystudies: No such file or directory

我究竟在做什麼錯?配置CDPATH後,我真的如何使用cd

沙发
0
0

下面是對CDPATH設置文檔:

cd命令的搜索路徑。這是一個以冒號分隔的 目錄列表,其中shell查找由cd命令指定的目標目標 目錄。示例值是「。:?:/ usr」。

因此,CDPATH設置不是一個簡單的冒號分隔的書籤列表。它更類似於PATH設置,因爲它在的內部看起來爲,每個列出的目錄都被傳遞給cd命令。

如果你想在這裏正確使用環境,我會嘗試:

export CDPATH='.:/media/user/01/workspace' 

...這將允許您根據需要執行cd rubystudies/

我使用CDPATH來保存.(當前工作目錄)和一個包含我所有項目的目錄,以便我可以從任何地方切換到它們中的任何一個。您可能還想包含您的主目錄以快速訪問它所包含的子目錄。

+0

我可以利用這個機會詢問如何從'CDPATH'中刪除一個目錄嗎?我沒有永久添加它,但是如果我錯誤地輸入了一個永久目錄,我將無法重新啓動會話 – sandobits

+0

刪除一個我知道的目錄的唯一方法是僅僅爲'CDPATH'分配一個新值有問題的目錄。您應該在「?/ .bashrc」中放置所需的設置,以避免手動定義它。 – lifecrisis

0
votes
answers
45 views
+10

Bash:從匹配變量的文件中刪除一行

0

我有四個名爲source,correct,wrong和not_found的文件。我試圖在bash中編寫腳本,其中我從源文件中讀取每行,將行存儲爲變量x,並將其與條件匹配。Bash:從匹配變量的文件中刪除一行

如果它通過,那麼我需要將該行寫入文件名爲correct,但是catch在寫入到正確前我需要檢查變量x當前是否存在於名爲wrong的文件中,如果是,請刪除它,然後將該行添加到名爲correct的文件。

下面我都試過了,但它不修改該文件並沒有給我任何輸出:

sed -i '/$x/d' ./wrong 
+0

我想你的意思是'sed',而不是'send'。如果你使用單引號,就不會有擴展,所以你實際上是在尋找'$ x'(字面上),而不是那個變量的內容。改爲使用雙引號:'sed -i「/ $ x/d」。/ wrong「 –

+0

感謝您指出錯誤。這實際上是我的iPad做自動更正。我現在糾正了錯誤。 –

+0

'sed'不修改文件:從標準輸入中讀取並在標準輸出上寫入。您需要將結果放在某處,然後替換原始文件。如:'sed -i'/ $ x/d'./wrong> ./wrong.new && mv ./wrong ./wrong.old && mv ./wrong.new。/ wrong'(如果您想保留舊的副本)。 – fernand0

沙发
0
0

正如你已經明白了,裏面'...'變量沒有擴大。

如果換成單引號用雙引號, 這將從./wrong刪除匹配行:

sed -i "/$x/d" ./wrong 

但你也想將行添加到./correct,如果有一個匹配。 要做到這一點,你可以在sed之前運行grep

grep "$x" ./wrong >> ./correct 

這將產生預期的效果,但 將sed覆蓋./wrong,即使它並不需要。 你可以防止像這樣:

if grep "$x" ./wrong >> ./correct; then 
    sed -i "/$x/d" ./wrong 
fi 
+0

感謝Janos,我實際上需要刪除包含x的行和從./wrong後面的下兩行。另外, –

+0

感謝Janos,我實際上需要刪除包含x的行以及從./wrong後面的下兩行。所以,我在做如果grep「$ x」./wrong;then ;sed -i「/ $ x /,+ 2d」./wrong;echo $ x >> ./正確; echo line2 >> ./正確: fi我正在運行一個單獨的for循環之前,如果循環保持行2和行3。我是否想從錯誤中刪除x的決定取決於line2和line3。因此,我不能直接從錯誤中直接複製包含x和下兩行的行來糾正。 –

+0

@DattarayaHonrao您正在添加不屬於原始問題的重要新細節。問一個新問題會更好,包括你真正需要的所有細節。 – janos

0
votes
answers
36 views
+10

將大型CSV文件加載到bash關聯數組中緩慢/卡住

1

我有一個非常大的CSV文件(~10mil行),其中包含兩個表示ids的數字列。要求是:給定第一個ID,返回第二個ID非常快。 我需要讓CSV的行爲像一個地圖結構,它必須在內存中。我找不到將awk變量返回給shell的方法,所以我想使用bash關聯數組。將大型CSV文件加載到bash關聯數組中緩慢/卡住

問題是,將csv加載到關聯數組中變得非常緩慢/卡住?8 mil行後。我一直試圖消除我可以想到的放緩原因:文件讀取/ IO,關聯陣列化限制。因此,I have a couple of functions將文件讀取到關聯數組中,但它們都具有相同的緩慢問題。

Here is the test data

  1. loadSplittedFilesViaMultipleArrays - >假定原始文件被分成更小的文件(1場密耳的行),並使用一個同時讀取循環來建立4個關聯數組(最大3個密耳的每個記錄)
  2. loadSingleFileViaReadarray - >使用readarray將原始文件讀入臨時數組,然後通過它來構建關聯數組
  3. loadSingleFileViaWhileRead - >使用一段時間的讀循環來構建關聯數組

但我似乎無法弄清楚。也許這樣做是完全錯誤的......任何人都可以提出一些建議嗎?

+0

Bash是不是非常適合此類任務。使用適當的編程語言會更好。 – janos

+0

你的問題是根本:你選擇了錯誤的工具... – HuStmpHrrr

+0

'sqlite3'或'mysql'更適合。 – dawg

沙发
0
2

Bash是這種大小的關聯數組的錯誤工具。考慮使用的語言更適合(Perl,Python和Ruby的,PHP,JS,等等等等)

對於一個只有猛砸環境你可以使用它通常與猛砸安裝sqlite3 SQL數據庫。 (但它不是POSIX)

首先,您將從您的csv文件創建數據庫。有很多方法可以做到這一點(Perl,Python和Ruby的,GUI工具),但是這是很簡單的在sqlite3的command line shellexp.db不能在這一點上存在)交互做:

$ sqlite3 exp.db 
SQLite version 3.19.3 2017-06-27 16:48:08 
Enter ".help" for usage hints. 
sqlite> create table mapping (id integer primary key, n integer); 
sqlite> .separator "," 
sqlite> .import /tmp/mapping.csv mapping 
sqlite> .quit 

或者,管的SQL語句:

#!/bin/bash 

cd /tmp 

[[ -f exp.db ]] && rm exp.db # must be a new db as written 

echo 'create table mapping (id integer primary key, n integer); 
.separator "," 
.import mapping.csv mapping' | sqlite3 exp.db 

(注:如寫的,exp.db必須不存在,或者你會得到INSERT failed: UNIQUE constraint failed: mapping.id你可以寫這樣的數據庫exp.db被更新,而不是通過CSV文件創建的,但你可能會想。使用像Python,Perl,Tcl,Ruby等語言來做到這一點。)

無論哪種情況,這將創建一個將第一列映射到第二列的索引數據庫。進口將需要一段時間(15-20秒與198 MB的例子),但它創建從導入CSV新的持久性數據庫:

$ ls -l exp.db 
-rw-r--r-- 1 dawg wheel 158105600 Nov 19 07:16 exp.db 

然後你就可以快速地從猛砸查詢該新的數據庫:

$ time sqlite3 exp.db 'select n from mapping where id=1350044575' 
1347465036 

real 0m0.004s 
user 0m0.001s 
sys  0m0.001s 

我的舊iMac需要4毫秒。

如果你想使用bash的變量爲您查詢,您可以連接或根據需要建立查詢字串:

$ q=1350044575 
$ sqlite3 exp.db 'select n from mapping where id='"$q" 
1347465036 

而且由於分貝是持久性的,你可以比較csv文件的文件倍該數據庫文件來測試是否需要重新創建:

if [[ ! -f "$db_file" || "$csv_file" -nt "$db_file" ]]; then 
    [[ -f "$db_file" ]] && rm "$db_file" 
    echo "creating $db_file" 
    # create the db as above... 
else 
    echo "reusing $db_file"  
fi  
# query the db... 

更多:

  1. sqlite tutorial
  2. sqlite home
+0

不錯!不確定爲什麼我的「exp.db」爲151MB,而你的是274MB?我在Mac上使用3.19.3版本。 –

+0

哇!這是一個很大的文件。我的'sql'超級生鏽,所以可能有辦法創建一個更小,更快的文件。這主要是我試圖通過的概念。 – dawg

+0

好的 - 在我的主要mac上試過,文件是158MB。示例CSV是198MB。 Hmmmm。猜猜這取決於mac和文件的歷史。第一個文件可能有一些事務歷史記錄。 – dawg

板凳
0
1

我做了一個小的基於Perl的TCP服務器,它將CSV讀入哈希,然後永遠循環查找通過TCP從客戶端來的請求。這是不言自明:

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

################################################################################ 
# Load hash from CSV at startup 
################################################################################ 
open DATA, "mapping.csv"; 
my %hash; 
while(<DATA>) { 
    chomp $_; 
    my ($field1,$field2) = split /,/, $_; 
    if($field1 ne '') { 
     $hash{$field1} = $field2; 
    } 
} 
close DATA; 
print "Ready
"; 

################################################################################ 
# Answer queries forever 
################################################################################ 
use IO::Socket::INET; 

# auto-flush on socket 
$| = 1; 
my $port=5000; 

# creating a listening socket 
my $socket = new IO::Socket::INET (
    LocalHost => '127.0.0.1', 
    LocalPort => $port, 
    Proto => 'tcp', 
    Listen => 5, 
    Reuse => 1 
); 
die "cannot create socket $!
" unless $socket; 

while(1) 
{ 
    # waiting for a new client connection 
    my $client_socket = $socket->accept(); 

    my $data = ""; 
    $client_socket->recv($data, 1024); 

    my $key=$data; 
    chomp $key; 
    my $reply = "ERROR: Not found $key"; 
    if (defined $hash{$key}){ 
     $reply=$hash{$key}; 
    } 
    print "DEBUG: Received $key: Replying $reply
"; 

    $client_socket->send($reply); 
    # notify client that response has been sent 
    shutdown($client_socket, 1); 
} 

所以,你的代碼保存以上爲go.pl,然後使其可執行文件:

chmod +x go.pl 

然後啓動服務器與背景:

./go.pl & 

然後,當您想要作爲客戶端進行查找時,可以使用如下標準的socat實用程序將密鑰發送到localhost:5000:

socat - TCP:127.0.0.1:5000 <<< "1350772177" 
1347092335 

作爲一個快速的標杆,它在8秒1000個查詢。

START=$SECONDS; tail -1000 *csv | awk -F, '{print $1}' | 
    while read a; do echo $a | socat - TCP:127.0.0.1:5000 ; echo; done; echo $START,$SECONDS 

它可能會稍微改變一下,以處理多個鍵來查找每個請求以減少套接字連接和拆卸開銷。

+0

嗯...這是OP的問題的大規模矯枉過正。你不這麼認爲嗎? – HuStmpHrrr

+0

@HuStmpHrrr不,一點也不 - 我認爲8ms很不錯。它已經在這裏9個小時沒有任何其他的建議... –

+0

謝謝@MarkSetchell,但我想避免使用Perl(我不想在組織中引入新的語言)) – treaz

地板
0
2

受@ HuStmpHrrr的評論的啓發,我想到了另一個,也許更簡單的選擇。

您可以使用GNU並行到了分割文件到1MB(或其它)大小的塊,然後用你的所有CPU核心搜索所得的各塊的並行:

parallel --pipepart -a mapping.csv --quote awk -F, -v k=1350044575 '$1==k{print $2;exit}' 
1347465036 

下注意到第二個在我的iMac上,這是最後一個記錄。

0
votes
answers
58 views
+10

交換從文件

0

通過cut -d":" -f1,3我做了一個新的文件,該文件是這樣的:交換從文件

username1:number1 
username2:number2 
username3:number3 

但我要說的是,我想我的文件看起來像這樣:

number1:username1 
number2:username2 
number3:username3 

我嘗試cut -d":" -f3,1,但它仍然讓我username1:number1,即使當我想成爲第三列是第一和第一列打印它像最後一列...任何幫助嗎?

+0

您需要提供精確的輸入和出把別人試圖回答的時刻輸入部分,甚至有 –

沙发
0
4

cut -f3,1將打印與cut -f1,3相同。使用awk

awk -F: '{print $3 FS $1}' file 
+0

不,我知道我知道......它現在的工作......但什麼FS意味着這個AWK? – blackroad

+0

'FS'是字段分隔符,我們用'-F:'設置爲':'。與'cut -d「類似:'' – thanasisp

+0

呃好的非常感謝你...... =) – blackroad

板凳
0
1

我喜歡這種事情awk。儘管你已經有了一個awk的答案。

在純bash中做到這一點,你會做到以下幾點:

while IFS=: read -r one two; do printf '%s:%s
' "$two" "$one"; done < input.txt 

IFS變量是用來切出輸入到單獨的變量read字段分隔符,和我使用printf爲我們提供可預測的格式化輸出。