C函数为shell命令参数转义字符串?

时间:2010-09-08 14:45:47

标签: c shell function escaping

我应该使用什么函数来转义C中的shell命令参数的字符串?

  1. 我有一个字符串:

    This is a string with () characters

  2. 这将是错误:

    echo This is a string with () characters

  3. 这些都可以:

    echo "This is a string with () characters"

    echo This is a string with \(\) characters

  4. C中是否有预定义函数将#2转换为#3

6 个答案:

答案 0 :(得分:7)

'替换'\''的所有实例,然后将整个字符串括在单引号(')中是一种安全的方法。这甚至适用于嵌入式换行。另一种方法是在每个字符之前插入\,除了那时你必须对换行进行一些特殊的处理,因为\后面跟一个新行被shell忽略,而不是作为文字换行。您必须使用'(单引号)包围换行符。

答案 1 :(得分:2)

没有预定义的功能。

但是,我认为只需将任何shell参数括在单引号中,并确保单引号被转义就足够了。

这是PHP中escapeshellarg函数的逻辑,我相信它运行得相当好。

答案 2 :(得分:1)

没有预定义,以及哪些字符需要转义取决于你的shell。查看shell的文档,并用\ X替换每个X.如果你所包围的字符串包含“。

,则使用双引号”将需要相同的处理

另请注意,如果您打算封装更复杂的表达式(例如,任何与';'复合的表达式),这将变得更加复杂

答案 3 :(得分:1)

C不是我选择的语言,但这就是我想出的结果(我自己必须回答同样的问题)。

#include <stdio.h>     // sprintf
#include <stdlib.h>    // malloc
#include <string.h>    // strlen

char* escapeshellarg(char* str) {
    char *escStr;
    int i,
        count = strlen(str),
            ptr_size = count+3;

    escStr = (char *) calloc(ptr_size, sizeof(char));
    if (escStr == NULL) {
        return NULL;
    }
    sprintf(escStr, "'");

    for(i=0; i<count; i++) {
        if (str[i] == '\'') {
                    ptr_size += 3;
            escStr = (char *) realloc(escStr,ptr_size * sizeof(char)));
            if (escStr == NULL) {
                return NULL;
            }
            sprintf(escStr, "%s'\\''", escStr);
        } else {
            sprintf(escStr, "%s%c", escStr, str[i]);
        }
    }

    sprintf(escStr, "%s%c", escStr, '\'');
    return escStr;
}

给定escape'this',它会输出'escape'\''this'\''',然后可以传递给echo

$ echo 'escape'\''this'\'''
escape'this'

答案 4 :(得分:0)

你的第二个版本很简单,不是吗?

printf("\"%s\"", your string);

答案 5 :(得分:0)

将每个单引号class ViewController: UIViewController, NSFetchedResultsControllerDelegate { public var cities: [City] = [] private lazy var citiesResultsController: NSFetchedResultsController<City> = { let request: NSFetchRequest<City> = City.fetchRequest() request.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)] let controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: AppDelegate.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil) controller.delegate = self return controller }() public var roads: [Road] = [] private lazy var roadsResultsController: NSFetchedResultsController<Road> = { let request: NSFetchRequest<Road> = Road.fetchRequest() request.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)] let controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: AppDelegate.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil) controller.delegate = self return controller }() func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith diff: CollectionDifference<NSManagedObjectID>) { if controller === citiesResultsController { for change in diff { switch change { case .insert(offset: let newPosition, element: _, associatedWith: let oldPosition): if let oldPosition = oldPosition { // was moved // HERE IT CRASHES let city = cities.remove(at: oldPosition) cities.insert(city, at: newPosition) } else { // was inserted let city = citiesResultsController.object(at: IndexPath(item: newPosition, section: 0)) cities.insert(city, at: newPosition) } case .remove(offset: let position, element: _, associatedWith: let associatedWith): if associatedWith == nil { _ = cities.remove(at: position) } } } } else { for change in diff { switch change { case .insert(offset: let newPosition, element: _, associatedWith: let oldPosition): if let oldPosition = oldPosition { // was moved let road = roads.remove(at: oldPosition) roads.insert(road, at: newPosition) } else { // was inserted let road = roadsResultsController.object(at: IndexPath(item: newPosition, section: 0)) roads.insert(road, at: newPosition) } case .remove(offset: let position, element: _, associatedWith: let associatedWith): if associatedWith == nil { _ = roads.remove(at: position) } } } } } override func viewDidLoad() { super.viewDidLoad() try? citiesResultsController.performFetch() cities = citiesResultsController.fetchedObjects ?? [] try? roadsResultsController.performFetch() roads = roadsResultsController.fetchedObjects ?? [] DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) { print("Now") AppDelegate.managedObjectContext.delete(AppDelegate.cityA) try! AppDelegate.managedObjectContext.save() } } } 替换为// // AppDelegate.swift // TestProject // // Created by Dennis Müller on 23.09.19. // Copyright © 2019 Dennis Müller. All rights reserved. // import UIKit import CoreData @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { public static var managedObjectContext: NSManagedObjectContext { return (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext } public static var cityA: City! func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. if !UserDefaults.standard.bool(forKey: "setup") { UserDefaults.standard.set(true, forKey: "setup") let cityA = City(context: persistentContainer.viewContext) cityA.name = "cityA" cityA.creationDate = Date() let cityB = City(context: persistentContainer.viewContext) cityB.name = "cityB" cityB.creationDate = Date() let road = Road(context: persistentContainer.viewContext) road.creationDate = Date() road.addToCities(cityA) road.addToCities(cityB) saveContext() } let request: NSFetchRequest<City> = City.fetchRequest() request.predicate = NSPredicate(format: "name == %@", "cityA") AppDelegate.cityA = try! persistentContainer.viewContext.fetch(request).first! return true } // MARK: UISceneSession Lifecycle func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // Called when a new scene session is being created. // Use this method to select a configuration to create the new scene with. return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) { // Called when the user discards a scene session. // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } // MARK: - Core Data stack lazy var persistentContainer: NSPersistentContainer = { /* The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. */ let container = NSPersistentContainer(name: "TestProject") container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { // Replace this implementation with code to handle the error appropriately. // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. /* Typical reasons for an error here include: * The parent directory does not exist, cannot be created, or disallows writing. * The persistent store is not accessible, due to permissions or data protection when the device is locked. * The device is out of space. * The store could not be migrated to the current model version. Check the error message to determine what the actual problem was. */ fatalError("Unresolved error \(error), \(error.userInfo)") } }) return container }() // MARK: - Core Data Saving support func saveContext () { let context = persistentContainer.viewContext if context.hasChanges { do { try context.save() } catch { // Replace this implementation with code to handle the error appropriately. // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. let nserror = error as NSError fatalError("Unresolved error \(nserror), \(nserror.userInfo)") } } } } ,然后将结果字符串括在单引号'之间:

'\''